~/f/erlang/RPMS.2 ~/f/erlang ~/f/erlang RPMS.2/erlang-28.5.0.4-1.1.x86_64.rpm RPMS/erlang-28.5.0.4-1.1.x86_64.rpm differ: byte 225, line 1 Comparing erlang-28.5.0.4-1.1.x86_64.rpm to erlang-28.5.0.4-1.1.x86_64.rpm comparing the rpm tags of erlang --- old-rpm-tags +++ new-rpm-tags @@ -3629,16 +3629,16 @@ -/usr/lib64/erlang/man/man1/cdv.1.gz 323e29d98125b1a8ca8d7ccbe7195438dae51abe80242ac05c4a3cb905b0ae3d 0 -/usr/lib64/erlang/man/man1/ct_run.1.gz e6b2613373dd290ec67549708cdeba6d3dfa83963fc2359521fef0639b4220ef 0 -/usr/lib64/erlang/man/man1/diameterc.1.gz baae897b063ada0caeb286061110dd9493b038566783648c80b2146d19bf7d09 0 -/usr/lib64/erlang/man/man1/edoc.1.gz 1710d3fc49d12a0734bab564c626d7db394b8045b98613e761bd806906b7e4b0 0 -/usr/lib64/erlang/man/man1/epmd.1.gz fc0debb3ca5f2e12d098756eac5bf3156f41316d2e7260a69017afd3d624de11 0 -/usr/lib64/erlang/man/man1/erl.1.gz d75a7cd1243dbad3247bf07728367db79274ee9bca69b3d4d567c3dc33dd8d1e 0 -/usr/lib64/erlang/man/man1/erl_call.1.gz d45550cd4d3ff6c8eec66caa83b34339fb6d839d167b1e8670b4455a9978c59e 0 -/usr/lib64/erlang/man/man1/erlc.1.gz 6c08cc0d3ce256435a0044ba46c94260d54674ef4f919e7e71be86ada1151807 0 -/usr/lib64/erlang/man/man1/erlsrv.1.gz 7f94f9467d4131de7ce0bdde1e0b02a24567ab48905376c9d0990354d2d0d652 0 -/usr/lib64/erlang/man/man1/escript.1.gz 03f5c28d8f60cf735619be587f53addb0cf2671e9030480263f3e155a35da212 0 -/usr/lib64/erlang/man/man1/run_erl.1.gz 2fd3825e64494e1bffae18ff666c99e8c4780360f1e943cdab77d2cb03e91ca0 0 -/usr/lib64/erlang/man/man1/snmpc.1.gz 823ea64be239584fb844d74ae937875009f8556105bb961086b30e98f05ffaa2 0 -/usr/lib64/erlang/man/man1/start.1.gz 484bc8d2d82d2bdff84333195c9a85c6201e412bfc511abd7e9207590e5e5bbf 0 -/usr/lib64/erlang/man/man1/start_erl.1.gz 87dcd25bebd2367fb0c82ca77b8ba4d29924c6a9cf7f27a03e476915471792bb 0 -/usr/lib64/erlang/man/man1/typer.1.gz ba57acc541158f915290582243a795575a25fb3f04610558c7761a524f403550 0 -/usr/lib64/erlang/man/man1/werl.1.gz 5cd6d95a419f455d8c3ba1137655c2d6c527555523c4935a0ee429ac83ca2f11 0 +/usr/lib64/erlang/man/man1/cdv.1.gz ba8d2241f68d18070b3eed9da1c8943f6a0a41bdad8cd5f3f42e78ce6814bb4a 0 +/usr/lib64/erlang/man/man1/ct_run.1.gz 3dab78baf39edcd508c556ece1ee4d63b855e9bd9f898267c7760c8d666b8de1 0 +/usr/lib64/erlang/man/man1/diameterc.1.gz d020fe3239051d93b26aba796763d975810b797d7c5ac11cc57f93e5215ba8e4 0 +/usr/lib64/erlang/man/man1/edoc.1.gz ad3aa9cde5a412b24a2714392dcf28dd8a3d2e3904f62496b272e0904390b726 0 +/usr/lib64/erlang/man/man1/epmd.1.gz e5a064163a12f00e1ad56481d2d7dd8c4c4a3fad1fe05609cee202c34263fce6 0 +/usr/lib64/erlang/man/man1/erl.1.gz b5485cc10a6b4102299966e38f7c2ee3653046e6d5bdcb0869f91c771371b6e4 0 +/usr/lib64/erlang/man/man1/erl_call.1.gz ee3302a9a4159b96a98997862aef174ba257d804f62f55aa00612e16b84160b0 0 +/usr/lib64/erlang/man/man1/erlc.1.gz 98c6f8b730f52ffb7773fc7df89fc869a69de3f0c92aba3d132c7c915b244d92 0 +/usr/lib64/erlang/man/man1/erlsrv.1.gz 4873712351aa1027f76427948fc96f91372656c9b9c9755bd6616d1ec3ae2fc4 0 +/usr/lib64/erlang/man/man1/escript.1.gz b2ac88feb47b9b3f214b3c9acfb50404245e7a1fa9c7d899c93d04602bd04740 0 +/usr/lib64/erlang/man/man1/run_erl.1.gz 2b12a1314acbd2e7f39384459de098ce425e71979d4f9cbe4a709999e7816cb2 0 +/usr/lib64/erlang/man/man1/snmpc.1.gz 28c0f99aa452112c92f7a2e4d212061387c5cc293ca9cb649953ea54c6d01252 0 +/usr/lib64/erlang/man/man1/start.1.gz 0851cbff6bd4c564d11929334a9d14c4bd122d5976454d6fd02b657b6f12b9e1 0 +/usr/lib64/erlang/man/man1/start_erl.1.gz ab7a073b8e2b9009313d8a60ba4c6f4ac33abcbd53b15a2baf44784477d201fe 0 +/usr/lib64/erlang/man/man1/typer.1.gz c4be64443160da7e62578b976d05a91a9058b0494a66470f3fd6a2aca7ddc713 0 +/usr/lib64/erlang/man/man1/werl.1.gz 7de1ef53050e158b1d18dcb93d98f5077d8e8bb59700fb1deadea165044b3631 0 @@ -3646,535 +3646,535 @@ -/usr/lib64/erlang/man/man3/alarm_handler.3.gz 2b321d25b6491e4039ace6d10d3453b3d2e0a882b002c4a36f9f26fa5b641eaa 0 -/usr/lib64/erlang/man/man3/application.3.gz 1d198ec3890569f096afc1239fdce05922c4dd9c92be2f084082b08f36f602b5 0 -/usr/lib64/erlang/man/man3/argparse.3.gz 3ddf870d4e2ac06e32b9df361b97035dfe396dae3979fc05ee3e308826013705 0 -/usr/lib64/erlang/man/man3/array.3.gz b5e4ffbd54309e657040e5580046479262d0118f1f82003ddf40214c29ba3d93 0 -/usr/lib64/erlang/man/man3/asn1ct.3.gz d0996fcd140b029c9f1ad89068709cfe5c9d9d4da9f8f1a9ff33ff5cff8b7dfb 0 -/usr/lib64/erlang/man/man3/assert_hrl.3.gz 59671f6ddb499a3b76eb0d4c8992fa5fc3ae70b4d9121199aca9d7536d03a97e 0 -/usr/lib64/erlang/man/man3/atomics.3.gz b4732091b83dd470e374850901095806f07cac754e5e682b5f91b2082bf447da 0 -/usr/lib64/erlang/man/man3/auth.3.gz 7b7fac6cad77dfea61a715b5615e1d21a79d155cc4e19cd1067f3972f6b0ac31 0 -/usr/lib64/erlang/man/man3/base64.3.gz 0742b57bff52f5f486dbae9280ab94d493383a88fbec5f14e45d7a02e38bab7c 0 -/usr/lib64/erlang/man/man3/beam_lib.3.gz 2541499a54d030a10e5acd6e99b026edb2477e4623257a11696ee17e1116b36e 0 -/usr/lib64/erlang/man/man3/binary.3.gz 5462ce9c20cbeaff0231d2843acde117aa5ad894e190d3b9e51955d4c297f99f 0 -/usr/lib64/erlang/man/man3/c.3.gz 7f00a9ed2b36fc0f33f11a1085a365780e37b76a9ff79077ef5378c59f8f5221 0 -/usr/lib64/erlang/man/man3/calendar.3.gz cef73e8503660e1b58500d42c1d2642794f83010bc5ea7865ff599948c441baf 0 -/usr/lib64/erlang/man/man3/cerl.3.gz 9ade9cb6951edc2ec22beb0f46383eb1a492f145f26cdb9a66d6b7049d57aa46 0 -/usr/lib64/erlang/man/man3/cerl_clauses.3.gz 9ef1a4f627b55042e336562fedfe6c388f64bf2d40f267ea8a516ed138f72156 0 -/usr/lib64/erlang/man/man3/cerl_trees.3.gz f36570e6d3b8a11c395ea680819a8db5a1fa889e89f3844aa65794941d653e56 0 -/usr/lib64/erlang/man/man3/code.3.gz f9b97aec9e4ca687caba330bf77cdda8391604223c5f6b554e6475b5a7a854b4 0 -/usr/lib64/erlang/man/man3/compile.3.gz 03d0149d9550873e7208f6827e96ea10a0c1f3780cbf95a61878bcc992a928b3 0 -/usr/lib64/erlang/man/man3/counters.3.gz 197dd5e5f734a623a5ccd6ac5041be2bf5edb321cf9f80933cf89e025bf81626 0 -/usr/lib64/erlang/man/man3/cover.3.gz d749e07fa56e2fd8a120c73f6b78177e19a6179617311cb05992dd0ea1158f19 0 -/usr/lib64/erlang/man/man3/cprof.3.gz 5808b1c3b53caed2e7e4c397fc224166bf595d84a31db7646ab9f4bf9dd7670f 0 -/usr/lib64/erlang/man/man3/cpu_sup.3.gz b608f5ed3777c626531b71e99599be5d8ded522b7198c3973cdafb3cf7c404b2 0 -/usr/lib64/erlang/man/man3/crashdump_viewer.3.gz d54eb72f8e7ce51ed3032c7fb2d44c19d7024a7361017902705a8754f5887b71 0 -/usr/lib64/erlang/man/man3/crypto.3.gz ddb4a96eab184979ea5c533f046e9fd1cb686616d00f5d018f915804b1a902d1 0 -/usr/lib64/erlang/man/man3/ct.3.gz c862cddf207b250ef6cb061607417dd24e927ca029f4cd685dcb60fde23cc48c 0 -/usr/lib64/erlang/man/man3/ct_cover.3.gz f3dd71b14410a2945649b14be4dd4b9a5a929b1980e8819c180666039a12e273 0 -/usr/lib64/erlang/man/man3/ct_ftp.3.gz d9ff621f462ffefb082b73a08d0f63258e970e8617eeebdde684fe6251d11ed4 0 -/usr/lib64/erlang/man/man3/ct_hooks.3.gz bd45338989ec70be5cbbd72976e78fb1f7e3969e3f4b7c96b8ec8bad5f1f4d2d 0 -/usr/lib64/erlang/man/man3/ct_master.3.gz 8cac9a712da37e7e5c5bbdac6d7f488d1db1c6a50e84f50576b71c36a72158f0 0 -/usr/lib64/erlang/man/man3/ct_netconfc.3.gz 71f528200c312fcaec20626e53dcabc88ca3ea67b67c2a9ad5b122ea1c6bc5c0 0 -/usr/lib64/erlang/man/man3/ct_property_test.3.gz 34c0c3cfad7d2c5053eab7a2e36b072cb4c904edbab4089c47969de0840a987b 0 -/usr/lib64/erlang/man/man3/ct_rpc.3.gz 187837c96b09165f28a65656501c56e81dce850a26b3ab4219d092f0ac386c67 0 -/usr/lib64/erlang/man/man3/ct_slave.3.gz 5a86c7cda1c373ba72d86f215af7b4e59057ab3571d2913ea770c072641b8a3c 0 -/usr/lib64/erlang/man/man3/ct_snmp.3.gz 2ab0d030192fb95bba4d984f29536723f7f5b9a6beda1653f400865f60e87030 0 -/usr/lib64/erlang/man/man3/ct_ssh.3.gz 8ffd2820ceda15571aea2719af92abb6657e7a72006898c8326df0d553022d8a 0 -/usr/lib64/erlang/man/man3/ct_suite.3.gz c724ebf0da9257c762770ec778440f10eb42cf32651c65b1dd1cc5709e62255c 0 -/usr/lib64/erlang/man/man3/ct_telnet.3.gz 9355c6a3ded0abcdf26112a44673a9fd1e7077c5e7d2cb496f0bb9c95430dbec 0 -/usr/lib64/erlang/man/man3/ct_testspec.3.gz 9b27817852af66e35cc711574c8160933e7a20eafa3aa27fc9a8a92fbb4b4302 0 -/usr/lib64/erlang/man/man3/dbg.3.gz 59bc1d423ac7b8deaaa20e6c7c493f911a2fa49dc8645889e19bfa5bef43d360 0 -/usr/lib64/erlang/man/man3/debugger.3.gz 2df034ec516e467f8dccb4c1f957cb2506bdc584365815e04434c68b4749c794 0 -/usr/lib64/erlang/man/man3/dets.3.gz 860cbaf1d2fa8e3bb9251b7f633c2ad96343374d52f13e6e8ea0470e0c882ac0 0 -/usr/lib64/erlang/man/man3/dialyzer.3.gz e961c3d70a39ff10f908775c7a0c9c2e41c23c7b5cd864c6a4e2e44132479ba3 0 -/usr/lib64/erlang/man/man3/diameter.3.gz 293efd51d8bf200178169e0dfa06b435511ed6ea5a7f404e1d2d284d6960dfce 0 -/usr/lib64/erlang/man/man3/diameter_app.3.gz 19a49aeb87d1b2d5a7ea5b96b7bca7a3766e50b843fdbb45ba77c2f5166ad888 0 -/usr/lib64/erlang/man/man3/diameter_codec.3.gz 0936b949aa0a99bf2c26a5c3bf1152a8f2d6245656fab7cd3bfce328d9177ff2 0 -/usr/lib64/erlang/man/man3/diameter_make.3.gz c4699bd6f9db69159913c151700ec1e6ba987a6d64285004d1113d47a6224b3e 0 -/usr/lib64/erlang/man/man3/diameter_sctp.3.gz 986d3ca6f2a1f70f7c0bbea99d1f860a1da46caa0aa98eb37ac35c45238a7292 0 -/usr/lib64/erlang/man/man3/diameter_tcp.3.gz 17d514fd027502a0d90837786dffca1ec7fc71f95e7a64add90737ed31b181e5 0 -/usr/lib64/erlang/man/man3/diameter_transport.3.gz 3aca7c7ffe1a5448cad89713c622ad802f2d889b3dd1ac8fb9425b425fbc1dd1 0 -/usr/lib64/erlang/man/man3/dict.3.gz 86465ee0fad815d3a2db3bd7030f9b1f5084bd3464422be23d0380ddef27b05b 0 -/usr/lib64/erlang/man/man3/digraph.3.gz cb599d2bc0830c7df6a0ef3dc8392fb2577b5117e02da6159eacfbb7cf750af4 0 -/usr/lib64/erlang/man/man3/digraph_utils.3.gz b1d624bda0e28de0974fd7fc3177465b43f6f96c54b466a2387022d62956f544 0 -/usr/lib64/erlang/man/man3/disk_log.3.gz 802507b5b4eb4ca68d5725968e3cf1e2a03e4301307870e5e351cfa3b8fa42eb 0 -/usr/lib64/erlang/man/man3/disksup.3.gz 5513392d6e2c00ecef0114e0b9fd78222c1be94e7fef8f7e4fa0405bd391ca61 0 -/usr/lib64/erlang/man/man3/driver_entry.3.gz c7d3b5d4ecc5cdc8e4be2d1036ab7c61bd9ad86f9c7c7ed47de89271f729da57 0 -/usr/lib64/erlang/man/man3/dyntrace.3.gz 745a2482b721cfcf052379c628f80ab1edec6635bfd6beeed3c50caf1b9667c9 0 -/usr/lib64/erlang/man/man3/edlin.3.gz 3d60d69818efc41f50822de6e569af4e59eb565449c79364dc969a539fa26c55 0 -/usr/lib64/erlang/man/man3/edlin_expand.3.gz e7c1c6a757a1feae348e4906f5b6586be5e8b250f48d7ee5434ce36e08535902 0 -/usr/lib64/erlang/man/man3/edoc.3.gz 797bf9ba0c0577f0c1163ee77fb5f735cb298a23ad97acf19384ce00bbc328a8 0 -/usr/lib64/erlang/man/man3/edoc_doclet.3.gz d0778347e684856bd1e7adbd35dc644c164e04e8ec2706782895b0afeb745f48 0 -/usr/lib64/erlang/man/man3/edoc_doclet_chunks.3.gz 8ec95ab0ede02b8974591339bd6b8a93c9da9c18a9ee6e25f948a0f6aca4a00f 0 -/usr/lib64/erlang/man/man3/edoc_extract.3.gz b2247c85dab82e09d3bb748ca2100444d5373523744e13712a9ae4a3a1af72fd 0 -/usr/lib64/erlang/man/man3/edoc_html_to_markdown.3.gz 3bfd8a8d37a9fdee648dfeb7c754c7e733b67590b798e5f435c309e5b9094ef7 0 -/usr/lib64/erlang/man/man3/edoc_layout.3.gz 5a72e06555ba0fe1fe51bbcc18bba6c02b15d3b30c30e55640b3ce09bf26dd46 0 -/usr/lib64/erlang/man/man3/edoc_layout_chunks.3.gz d7747eae43891f020d28909108277f6c4fd995cf22e10666d4f56f61ba48bf2a 0 -/usr/lib64/erlang/man/man3/edoc_lib.3.gz b03df6184ad2e05e4a7425c50b67a3fc55325cf4348447384aa45cf0f1655119 0 -/usr/lib64/erlang/man/man3/edoc_run.3.gz 7116a34206d20ed00db42d15113d5e9affcb20d9051ae5cba2e3af4dcf68214c 0 -/usr/lib64/erlang/man/man3/ei.3.gz 2afd377e7328dba9f7009fef7c327335e16abf6c826abe9f37b3b7b8f8cb6cd5 0 -/usr/lib64/erlang/man/man3/ei_connect.3.gz 4cef618fcca74459765ab14cac45e49bd36bf32005f77e70006f1de26067cb4a 0 -/usr/lib64/erlang/man/man3/ei_global.3.gz 156c9198796a7010840c039039b5d343ed5c8530fee50caf28ae3005e629f77b 0 -/usr/lib64/erlang/man/man3/eldap.3.gz 1a75188d8387290e5dd5c86ceb43a66f95eee9587609fef60d01e17981574962 0 -/usr/lib64/erlang/man/man3/epp.3.gz 66272941f7b8efc756460cb69e433e93ffebd77b0a6aca87164f733159478b37 0 -/usr/lib64/erlang/man/man3/epp_dodger.3.gz 3796327a65853b927d7390f129af45efcde43dc029fd4fe1c9e75635cb6f940c 0 -/usr/lib64/erlang/man/man3/eprof.3.gz e7cda7ded2b8858dcb593522ea3d507ff568535043c8acc80f95419749f3b9d2 0 -/usr/lib64/erlang/man/man3/erl_anno.3.gz b74ebcbef79e13743ffc257654441d701fa7168452b0a3f120778af3a03f132a 0 -/usr/lib64/erlang/man/man3/erl_boot_server.3.gz ef119b85b4f53cde7c06d131578ad9fceab5a4fb2db9ed8c7f362d4e95d568fd 0 -/usr/lib64/erlang/man/man3/erl_comment_scan.3.gz 47c502be3e77a78dca1e8f36cc112264b1973ae945d5f1e92bbb1e768530bf64 0 -/usr/lib64/erlang/man/man3/erl_ddll.3.gz b19e12e7ee66666f95a2c07da9cb58afbb02d0cb0e87a7904f8dec1115e3b72e 0 -/usr/lib64/erlang/man/man3/erl_debugger.3.gz 44ebba087e8c369bddc1039f1804fc0060f7d115188ecae8d440e12fe608fd11 0 -/usr/lib64/erlang/man/man3/erl_driver.3.gz bc3097118b89f144895074c1e7207991474cbba84c2296d38cc126c527eedb54 0 -/usr/lib64/erlang/man/man3/erl_epmd.3.gz 0ab084ba6f1a5151243dbd04cc3b714925c0161c2fa1da638998b395aa8ee402 0 -/usr/lib64/erlang/man/man3/erl_error.3.gz 847dd07a5d91441786f711037b869d4fbe6711adc3d16e2adee22aa79ec8ba5d 0 -/usr/lib64/erlang/man/man3/erl_eval.3.gz 6ec8997832a424afe8a00580887feb69e5aa65f944242a74a8918d5ee093233c 0 -/usr/lib64/erlang/man/man3/erl_expand_records.3.gz f2bc8586e4372d3f01fad19a487564ba843f32543af747a9ff56d6931a337532 0 -/usr/lib64/erlang/man/man3/erl_features.3.gz 0322c4e7ecd6bcc4b33bd6f637c61aa64702eb711d705d042cd85254ec5a4aa2 0 -/usr/lib64/erlang/man/man3/erl_internal.3.gz 1cbea460cd91f66d4e85e23153445fbc867dd156941ecc7cb6bf5166a72395cc 0 -/usr/lib64/erlang/man/man3/erl_lint.3.gz 0697a9fc9134986591d9dcef180ba9bd6062291080a0ee13f82c7833699f6089 0 -/usr/lib64/erlang/man/man3/erl_nif.3.gz 02ef0b4db1a0747a1726e5a9429a67d51c6151e0362ac3ec453e24ab6dc74d4a 0 -/usr/lib64/erlang/man/man3/erl_parse.3.gz ea6852ff2b96d2a5fa7ada01369c3a3d77b5c43f99a264eef4d24c6ace59dc33 0 -/usr/lib64/erlang/man/man3/erl_pp.3.gz bb8a6ab7ff32b9b6f0e40e0f90c5b824a2ec10956c181e388481bc8f4d15104d 0 -/usr/lib64/erlang/man/man3/erl_prettypr.3.gz e6923fd65f807ce5723a33fa0c7697058e51094cbf12254283a7dc38678a1b88 0 -/usr/lib64/erlang/man/man3/erl_prim_loader.3.gz 1e384d9e62e9a7a020ad504e29f27f849c9fc436eb82c4ad29de0439451d3e8d 0 -/usr/lib64/erlang/man/man3/erl_recomment.3.gz e9d896b283a7f4ebe108d016737e9ab56114e251553faf97af030f3c898c1382 0 -/usr/lib64/erlang/man/man3/erl_scan.3.gz 23f54935e4e063ad728cdc0c9c110e6df3699403551b1e2a69db2b6104f4b74e 0 -/usr/lib64/erlang/man/man3/erl_syntax.3.gz cd102403fcc4b0b966137967d3a3cdf5ddd299f839143628e18e974d10e029a5 0 -/usr/lib64/erlang/man/man3/erl_syntax_lib.3.gz d5311081740721d128764000fc183670799c5951b162455e57c8b6170308d17f 0 -/usr/lib64/erlang/man/man3/erl_tar.3.gz 884142ad9c523c80980964c8e53f955ab6a1d2215a636224243420f154680e4e 0 -/usr/lib64/erlang/man/man3/erl_tracer.3.gz 540c9759f327fbb52b680a2caa123dbddc62cc32dff634b8032cb6894eebd831 0 -/usr/lib64/erlang/man/man3/erlang.3.gz d619504f771c8c873402895836ff1ff352a33619abf02926b75adc4b75cd49fd 0 -/usr/lib64/erlang/man/man3/erlang_port_info.3.gz 54b88a6dccb8741e77a9578c38eba9c0f5b36c0dba5a855ed55ec6353ba1df90 0 -/usr/lib64/erlang/man/man3/erlang_system_info.3.gz 68884188727715e79a201d6508be21a80b1dfc3a76c2aea41c107f9fb654e08a 0 -/usr/lib64/erlang/man/man3/erpc.3.gz 4987595d5fd7da23ab925b3ce50dec402f702a94c593031ce41a2dab9670dc80 0 -/usr/lib64/erlang/man/man3/error_handler.3.gz 8ffde4fd1342907bef1b25fcb7f0bce99012cdfe54026bf71e9c4a4dbea78e56 0 -/usr/lib64/erlang/man/man3/error_logger.3.gz 13a9454c426580d7328f779872d000dee3956f35a8b5e4407483d402204b2e18 0 -/usr/lib64/erlang/man/man3/erts_alloc.3.gz 7735b7b723493d751f739f4c18790b774e80326fa432003d7cc6529263d7119b 0 -/usr/lib64/erlang/man/man3/escript.3.gz c824a5317d544df9e441b03717ccc4da2aad63cf310a13418e54d32221040feb 0 -/usr/lib64/erlang/man/man3/et.3.gz 1d3b64bf6952b94d48e8b6a7914bc8b2a5fe338d5fbe1c53b9e1e983675965b2 0 -/usr/lib64/erlang/man/man3/et_collector.3.gz a693d57ab7d26644b73ad52ae94e648918278dd2c28b7a7237b0b4ce5a87e214 0 -/usr/lib64/erlang/man/man3/et_selector.3.gz 31cfa1538416332d8a8218c9485bc5592af669298c4afbc2916506cc1f9c54d9 0 -/usr/lib64/erlang/man/man3/et_viewer.3.gz fd20fd9c686c53159d2cdd385e6e89334fbbc19dc98c380f012e6e2dfa2e2098 0 -/usr/lib64/erlang/man/man3/etop.3.gz 3d899b8cb13c4a99d62605fdcec13b1bb90a225dc086c44deb4a2da8515413d6 0 -/usr/lib64/erlang/man/man3/ets.3.gz 5c5cdb721d4f6aa2c736d68873c4b67be9af55117196e19184c090ba105963b2 0 -/usr/lib64/erlang/man/man3/eunit.3.gz d0597c7fdf67a5d5b3cc505c6a4ae5ededba888a375b4105543b92c32ed93105 0 -/usr/lib64/erlang/man/man3/eunit_surefire.3.gz 1b98d06fa5c27ec01d04410382fef27cc7cf7f0fa1a455287e0376a14780b3e6 0 -/usr/lib64/erlang/man/man3/file.3.gz fbd8f4afc1e9bd5ad78127edc3641964f50ff346876afa90f968ed0342714897 0 -/usr/lib64/erlang/man/man3/file_sorter.3.gz 4f763527e54213433d661902eee3b427d97640821031b8c3f86125de8582d811 0 -/usr/lib64/erlang/man/man3/filelib.3.gz d4d57836145d64dbb403c6443c26f60af24d2bfdd687035f3d772be466211b06 0 -/usr/lib64/erlang/man/man3/filename.3.gz d139e9a8cf73a7d97b4609947378ffd54b67958b5a0aa61c166c5aba0c2a2e24 0 -/usr/lib64/erlang/man/man3/fprof.3.gz 64cef614e3004a9c9695139f8d99236f6d985723135477ae461a53a189eda91d 0 -/usr/lib64/erlang/man/man3/ftp.3.gz 9865f61f09d7053a5eeb516f7d58f1e817fc78777dd257443ecedae569dd984a 0 -/usr/lib64/erlang/man/man3/gb_sets.3.gz 62aa1147a9de6754ea0e95c5a8b8501ef0de9d04b9e0b96779305a8f8bab6fb1 0 -/usr/lib64/erlang/man/man3/gb_trees.3.gz 9d4ec57e81b375de817c2a9595ad8083b0d79e38edbb95ee9ef79c2c8ba1972b 0 -/usr/lib64/erlang/man/man3/gen_event.3.gz 62be5c4008369e2f8cdf299490d5878e416ac8e0322bcf16c73e2f75e3a23597 0 -/usr/lib64/erlang/man/man3/gen_fsm.3.gz decd42c3c1af974b18edaabdb8fa695848336be508aa9d541f1ba3892a1e7172 0 -/usr/lib64/erlang/man/man3/gen_sctp.3.gz cb0e14549c2b398f48cb2ed3db5ddc4ef89623cb742884f00e02fa06c11b4b67 0 -/usr/lib64/erlang/man/man3/gen_server.3.gz a01ed6d5a1370ad3245a7ec9ef3d0ffb8038fae96d96482c195edfbc4568b61d 0 -/usr/lib64/erlang/man/man3/gen_statem.3.gz 7c54b195765a2e6f0d026d724a2ab36c336d03ad3f130019360fad8976b8d205 0 -/usr/lib64/erlang/man/man3/gen_tcp.3.gz 07ff4ff9d26e9a6840dbba43074720e00db0ac7ce76c98c8257e77f3bb58b8ab 0 -/usr/lib64/erlang/man/man3/gen_udp.3.gz 0cc1b6f0ab3b81ad59dfd1f12c7e64d6d815c84921d9c9326e2b4bc67c6bcf10 0 -/usr/lib64/erlang/man/man3/gl.3.gz e7bfa54867438e8ad07c3571721a0e6ac3a3966e9411ccc7d79ccfc779fdbef1 0 -/usr/lib64/erlang/man/man3/global.3.gz f0aeeeabe6bc9a99d24e6127a64b5fb0005655688f36312a9c886f67b3afef7c 0 -/usr/lib64/erlang/man/man3/global_group.3.gz 141277b541eb96bf4720adb21d64f078c94f93023076e921356b122c76c89982 0 -/usr/lib64/erlang/man/man3/glu.3.gz fda8a9075c59bdb7aafd8d7bc3fe7cfc7374911d38c877c6dbc66cb065e1d832 0 -/usr/lib64/erlang/man/man3/heart.3.gz db50cf242ba0fd7cd3e0ca93897ca37406fa64311d44310f47a1935366f7ed14 0 -/usr/lib64/erlang/man/man3/http_uri.3.gz 90694517388bf9582f9720042688a49360473c9c76debc15ddbfde2e25b85e5d 0 -/usr/lib64/erlang/man/man3/httpc.3.gz b762586e9bc4e22aca52cfaddfa802ed040694eb158f56683ffadbae8aca0a91 0 -/usr/lib64/erlang/man/man3/httpd.3.gz 2a568310b7a877862971746aac71c98d33021daef0c35db35edd03dcf59cf681 0 -/usr/lib64/erlang/man/man3/httpd_custom_api.3.gz 2de336b0473e053addb46d387d3dbc953b3289948125029e49ab910616f58309 0 -/usr/lib64/erlang/man/man3/httpd_socket.3.gz 0e865984e2ba0af193ff0f5bd54144be24ee24df1b1033eb4fa6d8a2f3e52bc9 0 -/usr/lib64/erlang/man/man3/httpd_util.3.gz c2baa22b4b52245a493fa31ac8c995e7cdb0986729430063220141922cf572e4 0 -/usr/lib64/erlang/man/man3/i.3.gz efeaa9491653028df4785525ae5edad29449f26dc22dc03095b6df8e7f1766a3 0 -/usr/lib64/erlang/man/man3/inet.3.gz 68a7bdca6199f0730e800295abe50e4b97433568fa1273cc5c59d384ce02d135 0 -/usr/lib64/erlang/man/man3/inet_res.3.gz 7573c6bfb6dd7a50f9b51bca7900714e5156372fd52452490a120076bfca8600 0 -/usr/lib64/erlang/man/man3/inets.3.gz c105b3cba7f6dedb2d75d6d096b2efa870895b76e69496d5e92a65733c8f9bce 0 -/usr/lib64/erlang/man/man3/init.3.gz cf697ba746243419cb3679cdbac1a735463fa43cc1f3c8782247999d4862757e 0 -/usr/lib64/erlang/man/man3/instrument.3.gz ec3e4d048c93335d28d2b9d84a3b88f84afb06e60689199c6096e9639a2b39cf 0 -/usr/lib64/erlang/man/man3/int.3.gz 65657acb62b3beda8821ab8b27d5960bc4a204212c86913080557759f500c92d 0 -/usr/lib64/erlang/man/man3/io.3.gz 12a2b8e6afc54e35f9c4ed822f43682b73c256f13346680f8b639c633178fbcd 0 -/usr/lib64/erlang/man/man3/io_lib.3.gz 16688445672c5ad25445e9bde83cc4fc92442a9395882c7279f05ce68feecfd7 0 -/usr/lib64/erlang/man/man3/json.3.gz 6154fe511fdaea92178eee5cbf6ab0fa8006095fc214274b703565c4dd12b2c7 0 -/usr/lib64/erlang/man/man3/lcnt.3.gz b12ed2235ade94d56c299b09cc7a9859badef6bba4cd591508d8594770e3d944 0 -/usr/lib64/erlang/man/man3/leex.3.gz 47cc5185bf22637281bbe21626f310c2ca0a1ba715a90ff36cfff320a6fb7dd6 0 -/usr/lib64/erlang/man/man3/lists.3.gz 0a7a2a467229f8781110608ec38e78eec7af55bbd8f312b4e504514359a7ffe2 0 -/usr/lib64/erlang/man/man3/log_mf_h.3.gz 3b22c037f2119d6304642a3cfdc419697fd4489b6af5a6913a8c2f050c0bfcd0 0 -/usr/lib64/erlang/man/man3/logger.3.gz 18c22531a1be5f4ce94928fe149819dbd86c0fae57a5e135978b94df5ffbca22 0 -/usr/lib64/erlang/man/man3/logger_disk_log_h.3.gz 6cc79f8e7709046c3f48591de838e6ba081597e01675d6e70bd53b288bffb4e9 0 -/usr/lib64/erlang/man/man3/logger_filters.3.gz b8c68f62f7d6a1822c8f020f7b3500a32cc01b29986ada68e68f2aa32e6c0f1f 0 -/usr/lib64/erlang/man/man3/logger_formatter.3.gz a935a2cd9c3710e4240d202a9f1694a0ef3f2304a3b3422a19f07fe9e3c4bdbd 0 -/usr/lib64/erlang/man/man3/logger_handler.3.gz 697fc372eb52c31f7e9aec48a9f5c659c4f538e7358248ea0fb0ebd6bee60596 0 -/usr/lib64/erlang/man/man3/logger_std_h.3.gz fcb1bd8e3674d017d89d061598147406aa0c8b3bce545b8e2b79fe319a0802cc 0 -/usr/lib64/erlang/man/man3/make.3.gz 8af3a318c750f0beb978eaad67f6ed10b6f22ebba2351432cd0b19d6d8fa885d 0 -/usr/lib64/erlang/man/man3/maps.3.gz 5ce83d20272a2adf32a43c1d9b96f20285337d66b9575b589604e3dea1424a2a 0 -/usr/lib64/erlang/man/man3/math.3.gz 1621438383d510c4decb72771d637cca1e834879948e73c3d4d7ff1de80e9b51 0 -/usr/lib64/erlang/man/man3/megaco.3.gz 040984f21cb43ddefeb6ee91279c1e96c6d55c4ef62ed334b408490429e69248 0 -/usr/lib64/erlang/man/man3/megaco_digit_map.3.gz 14b1d86687626488f7555fcc25fd4fa2f11e7d730d369a6744ff3530387f3c51 0 -/usr/lib64/erlang/man/man3/megaco_edist_compress.3.gz 569b052e869574916cb3ffe68a79ee5e44e81d012f4bbeefa27b2a0a2028d316 0 -/usr/lib64/erlang/man/man3/megaco_encoder.3.gz 3999e2959c451953b9279f3b53ea1448225a4c9b1f44ee66d691b2094e31ec34 0 -/usr/lib64/erlang/man/man3/megaco_flex_scanner.3.gz fe9b7e15108f4d099effb69887852896bac217f377f0c9fd93cc526ac01b586e 0 -/usr/lib64/erlang/man/man3/megaco_sdp.3.gz 355c6b3d9ab190beb777aece77e1083b409d1e49bf06d917778911e99e67aff1 0 -/usr/lib64/erlang/man/man3/megaco_tcp.3.gz 2faa5f60842b653c1540812b9e48121ebc47706ddaf369541d371bcf8d226d71 0 -/usr/lib64/erlang/man/man3/megaco_transport.3.gz a0db7351e7db55867c82a482ff4d2d8779f3efa300139433892a2d62384b9221 0 -/usr/lib64/erlang/man/man3/megaco_udp.3.gz a84bdfff523452961d2499600856118881a4fc73327daa0be5c76f4ef622bd97 0 -/usr/lib64/erlang/man/man3/megaco_user.3.gz 14ef9d9a939c51afa663224311e9e77b7a0ee9dc37c5d6fb27b643a9afb59543 0 -/usr/lib64/erlang/man/man3/memsup.3.gz 99672e09a1dc88d02bd5aa25ab617fd6c85fad2e6e35c7976a7f590c83289ca1 0 -/usr/lib64/erlang/man/man3/merl.3.gz 3bb19db70eba370fe6c147864ae03fffb6d30cc842a79a4f53f7a2abf89046df 0 -/usr/lib64/erlang/man/man3/merl_transform.3.gz fe9ad67576d4b533b53148508d87f924c27866a0f7f53e4eb4f8fe9e31e6890e 0 -/usr/lib64/erlang/man/man3/mnesia.3.gz ec57245625fe1a62ee14eb681e0fadd73c18c6e252ca849f4476cccd39d490c0 0 -/usr/lib64/erlang/man/man3/mnesia_frag_hash.3.gz 1b239cb521d3c7dc327f74f455f90c363a8fe1ed7186c6da1ef7c486a89050ee 0 -/usr/lib64/erlang/man/man3/mnesia_registry.3.gz 016a85eaafb70a27b8672201f03ef8044c92efb6535762e904a1206a6e7e6c06 0 -/usr/lib64/erlang/man/man3/mod_alias.3.gz 664e99ced321910620918aa32cd9f2ba1ab9679abf6b7ac7034e5ad9b10045e3 0 -/usr/lib64/erlang/man/man3/mod_auth.3.gz ab4748f18cfd95a3c561ec3c4a91b3846909e70032069451c5a80311428e8dce 0 -/usr/lib64/erlang/man/man3/mod_esi.3.gz c75756977de12ddef3d0f881a3051117c1cb67938f93b49e5706f12153da4605 0 -/usr/lib64/erlang/man/man3/mod_security.3.gz 816dbec93faedd98f709a7c32b5cda07410ad4260db513d85f4a4378c52e4513 0 -/usr/lib64/erlang/man/man3/ms_transform.3.gz 52e8e52d095d006b7befcab8d9861a66295daa1f33f12328f92099d334076680 0 -/usr/lib64/erlang/man/man3/msacc.3.gz b4a9d359934ab26e6b33c63a2a0babdf8962f93423d6c6c359c08f616a6b1d76 0 -/usr/lib64/erlang/man/man3/net.3.gz ab1adad18cc691c451961bcb1553aad44a338679f37d4d83ccc2f8d3c0f57a97 0 -/usr/lib64/erlang/man/man3/net_adm.3.gz f47c03d1cdbd113603b46e5a115839c4999e3b3c676d71e06b6f2434cabe5e6d 0 -/usr/lib64/erlang/man/man3/net_kernel.3.gz 075e8939baedb8938746c24ebca6d9b3a3f5377303810df22a2ff1b1e4906eca 0 -/usr/lib64/erlang/man/man3/nteventlog.3.gz cbe96645421a601a3dec360dfbb6aed7d043ef97816440dcd64380706c83a7b4 0 -/usr/lib64/erlang/man/man3/observer.3.gz c46aa483b816c48abbad4c9a7b4c76cbab7f9a35d893b4c498c5c91df52a34e1 0 -/usr/lib64/erlang/man/man3/odbc.3.gz 34753241948596a7a57969b9512c2c0389cff38a461dbe38f22d7127bab45b68 0 -/usr/lib64/erlang/man/man3/orddict.3.gz ebcfaa42b4f3910fb78e3b17216309dffdaf8dae7b0102a573bd85d61243dd4b 0 -/usr/lib64/erlang/man/man3/ordsets.3.gz 7354feba63baa1635f2f9f9fb021f472f566c1e7a45365c208d399018fdf5e98 0 -/usr/lib64/erlang/man/man3/os.3.gz 85f512ed65c22d13f8e9a692201c0f2982aa9af018d3d70e60404a09e0593c60 0 -/usr/lib64/erlang/man/man3/os_sup.3.gz 29ff3f97afca65a7a1344ae1584be6dbac1d043d6f40e6cac73561233088ca09 0 -/usr/lib64/erlang/man/man3/peer.3.gz 2fbba9894e1ff5d691456642c20772ad340c2b4a65b4a1ee4d5f16884977f2d8 0 -/usr/lib64/erlang/man/man3/persistent_term.3.gz bede37078d297a2f5d33d041ebab401671cc04ee171e9655905ccf17f781c17c 0 -/usr/lib64/erlang/man/man3/pg.3.gz 3783b07c2632faf85446527d8febf514c6abed80af1d314e4c9026c7bf5cd66e 0 -/usr/lib64/erlang/man/man3/pool.3.gz d3e1cc1c1da1e58e2ea087102c1aa4bc06e21556767d762652983e493a4e4c39 0 -/usr/lib64/erlang/man/man3/prettypr.3.gz 36edc3d6fbc35f94fd35cc2c7ef42941ca70133350bdc650ac92278f175dbdb9 0 -/usr/lib64/erlang/man/man3/proc_lib.3.gz d8c57ac08f86f6afc47d4d7605a6a1afb47e5ab5ca4aa7ac5dddc34c472fcaad 0 -/usr/lib64/erlang/man/man3/proplists.3.gz f678ecd2dbcb44b74367a42d72b36a829d97162daf1fd9496c3e756b82e72ed6 0 -/usr/lib64/erlang/man/man3/public_key.3.gz a280d5eac5e60e0873604818d533ab893b800ddb48fbc3957e8a2c96ea73ccb8 0 -/usr/lib64/erlang/man/man3/qlc.3.gz 431320d021bfa526958f29ed5e8b5360c1e537bc1eec85b38af9990154fa7ea6 0 -/usr/lib64/erlang/man/man3/queue.3.gz a832180945278ed9a9ba8fe446cc999e8397dfebbf79e8660739db8782a7435b 0 -/usr/lib64/erlang/man/man3/rand.3.gz 6f6b5f7a2593b9fe237b681818a2ce0282a3b5443ad79ca7ebf736aca3f01620 0 -/usr/lib64/erlang/man/man3/random.3.gz c687d13f312eac0afb40b3111e3960f2ccd529d42f1478b6ee4d20b70a62d0a2 0 -/usr/lib64/erlang/man/man3/rb.3.gz 03ad3d6995d75c8370e5dd9e74a93a8ab4950226331488c2542c2fec551ddb35 0 -/usr/lib64/erlang/man/man3/re.3.gz 6f2a58b468b6edeae6398e79c09aaca97ccf06eaed2ac9b99ad5c9494774e132 0 -/usr/lib64/erlang/man/man3/release_handler.3.gz 7e16e9c97751026cea4e3881c75704f21ed278ac19fa6ea0d0270ba34cde06c8 0 -/usr/lib64/erlang/man/man3/reltool.3.gz 6be514173daaec900ae23dc073a1d8ce6e8168465b7d3dd795dd6fe449f68ddc 0 -/usr/lib64/erlang/man/man3/rpc.3.gz 1e4c676290f40bee35644506a4ed7396cf3d54e031430ad12688bba25c938e4e 0 -/usr/lib64/erlang/man/man3/scheduler.3.gz 2b6b6284f528ab2770bd8a45e55d4bfd8f867bffff29c92241cc7ebf396fcfad 0 -/usr/lib64/erlang/man/man3/seq_trace.3.gz dd7a9c43fbb0b957e7b4aa3b96a14c25294f1c5c7300f75eb2d818f6ed46f0ad 0 -/usr/lib64/erlang/man/man3/sets.3.gz 2425ec21720b61d8a2a79e845be79eeaa261e10f549170860e50755bd71cd9bb 0 -/usr/lib64/erlang/man/man3/shell.3.gz a387c9d4c9290655ce64b33081a5f9a287f71bbe894c23c7eac955bd5185c299 0 -/usr/lib64/erlang/man/man3/shell_default.3.gz e53c7e61b5835342f8cf878c19a0cf8c864c3966444cb5b7ec76f361720c5106 0 -/usr/lib64/erlang/man/man3/shell_docs.3.gz 6e4267e79fa765fe303ea22ec17e410375bc86f6fa454217a2fbe8aea7256ad7 0 -/usr/lib64/erlang/man/man3/slave.3.gz 97c0c277d0be4e55ba23a9563a51a283419c5efdef02f088eef09bff63948d56 0 -/usr/lib64/erlang/man/man3/snmp.3.gz 5ff8d0922852877fe7f8da57288fb02c51ef722d79994b839de15856f7bdc5d8 0 -/usr/lib64/erlang/man/man3/snmp_community_mib.3.gz df4ef3b27fec8cc492d2a2ff968318c4228654855848e941b86a0fbce502d41b 0 -/usr/lib64/erlang/man/man3/snmp_framework_mib.3.gz 45e33a350fd66f85dce33fda1d938a437c653f773aef95064ed285f13816f057 0 -/usr/lib64/erlang/man/man3/snmp_generic.3.gz 63c7306b4ddc76a9ee0eec0c0b76eaf7c4c7d44afe6b17461d65ff05fca54ece 0 -/usr/lib64/erlang/man/man3/snmp_index.3.gz e12190eeb1f56cb70eb67d8bd380ddf5960ef822633eb36b60016fd9e3c35800 0 -/usr/lib64/erlang/man/man3/snmp_notification_mib.3.gz 023c310f5a0bddd8791124967fa34fd0e500d98ad02746b6d068af67db45b598 0 -/usr/lib64/erlang/man/man3/snmp_pdus.3.gz 9d6946dbf7db8a6ba2ee050c1b37253ce117102640d53b509d3bd00d6e9f8f0c 0 -/usr/lib64/erlang/man/man3/snmp_standard_mib.3.gz 687c9a730d0b19fa9dd2b6463527275afdf12626f199e6a4d439cc899eacb62b 0 -/usr/lib64/erlang/man/man3/snmp_target_mib.3.gz c2d7c066408e7dffeb0910641dc82ec855f1f02922ecc3c2d24c8e93e3bcd8a7 0 -/usr/lib64/erlang/man/man3/snmp_user_based_sm_mib.3.gz ec4bbdad23f1c644abf16de632e8496c9c4bb90f2aee275cf25aab05deea223a 0 -/usr/lib64/erlang/man/man3/snmp_view_based_acm_mib.3.gz 5002be04a0c6ab1905b2588fd8b6cfbd96a0a9373a3e28e1ff95cecbdec38acc 0 -/usr/lib64/erlang/man/man3/snmpa.3.gz f543ebd16ae5a2417283779ba7c8279495ce789fe8a90db8890b0d860a31b6b8 0 -/usr/lib64/erlang/man/man3/snmpa_conf.3.gz 39fbf0b1c019373ad4379cad5a274d062b6e3671ed412b4f40866b10d385b570 0 -/usr/lib64/erlang/man/man3/snmpa_discovery_handler.3.gz b525056ef80eae9cbec5143938205a88b385e1daaaa376265b00e33428722f14 0 -/usr/lib64/erlang/man/man3/snmpa_error.3.gz 48d270d1d6c339c87607b64ce6cdfe5ee9131e526c6881b8a03741818b1ad074 0 -/usr/lib64/erlang/man/man3/snmpa_error_io.3.gz ca74915927890ef19defb595a0f8c3bf94bfc51a4f027b18f3888f4ed05c16a3 0 -/usr/lib64/erlang/man/man3/snmpa_error_logger.3.gz 2261734cdf3a8350efbcbd6f0267e131d8ca889715723fc59412efc1f947dcd5 0 -/usr/lib64/erlang/man/man3/snmpa_error_report.3.gz c1474919d02622e09e7b03b6b76411157804515224151ff4c6d55cb5d16edbbb 0 -/usr/lib64/erlang/man/man3/snmpa_local_db.3.gz 0abf27eefcdb0368d21116fe924f61cc6c8f93e75444647f4a8157d1ced1e0b1 0 -/usr/lib64/erlang/man/man3/snmpa_mib_data.3.gz aaea5196ad76ba2f5c22f867255acb9bd339e8f431f456470311a2c567ee85e2 0 -/usr/lib64/erlang/man/man3/snmpa_mib_storage.3.gz cc0be1d4ce9464c1b1980c3b4559835103a49f48c8fc22dec8249c5708f345c5 0 -/usr/lib64/erlang/man/man3/snmpa_mpd.3.gz 01845f0d6b2143576a3c4faec2373cf837b2735fac5a32c78c4a1cb6a242ac94 0 -/usr/lib64/erlang/man/man3/snmpa_network_interface.3.gz bc392aa46c6d34b6feb312d667f7eca42dcadd3dcc5391e00189c915bbd52ffd 0 -/usr/lib64/erlang/man/man3/snmpa_network_interface_filter.3.gz e47ff2e55a82111e83b2b33c98cba33b1f907a771a2062e06afec5f49e0f1b5b 0 -/usr/lib64/erlang/man/man3/snmpa_notification_delivery_info_receiver.3.gz 159a64df819a661100b34551864f978d6ab60efec89303864d16f75012f83836 0 -/usr/lib64/erlang/man/man3/snmpa_notification_filter.3.gz fc17d703dd4d67ee1fdf10b26cd31c03393640c70eece4cf454e4a6b7533440e 0 -/usr/lib64/erlang/man/man3/snmpa_supervisor.3.gz 73553c00a208c088acada8224f9fbb9b8bdedcd5d7bbd377bac800c11bd68322 0 -/usr/lib64/erlang/man/man3/snmpc.3.gz 7bad0afd4ef5fc07bcac8e653899448dec57d8ba260bb759e9e85b40b744c350 0 -/usr/lib64/erlang/man/man3/snmpm.3.gz f9849303e1fbba8e17a4563c30ebfdf3271e1e259cccfd9dbcbb0858ba997cd3 0 -/usr/lib64/erlang/man/man3/snmpm_conf.3.gz 201eefbfa36d8b117f603c7d5bcc9dea043269574d349da271d5e1f2a3b8f31e 0 -/usr/lib64/erlang/man/man3/snmpm_mpd.3.gz 039551a925dfbf1cb55690cd3962f8e37df3f2e91d018a3a7e02ce7955b884db 0 -/usr/lib64/erlang/man/man3/snmpm_network_interface.3.gz 576812ff476a42fc4f829b46ac6191d984cfb199f14adcb6caf99e752b8b6ca7 0 -/usr/lib64/erlang/man/man3/snmpm_network_interface_filter.3.gz 48e55d56603126457315c8e333f966ecc03a6ba097346f1ac1d5deee464d6f36 0 -/usr/lib64/erlang/man/man3/snmpm_user.3.gz 6a81dfbff8abda8bbffc27676501ee2f7a903cb7748e998d38c5b3e406f26508 0 -/usr/lib64/erlang/man/man3/socket.3.gz 8f2118af0a5fa226799340ed39c810af93a501a3ebda08079c56719d69427dbb 0 -/usr/lib64/erlang/man/man3/sofs.3.gz 5878d6dc54e479e1c1153e3f5ba923cd83c273fdfc0d8d7f73513b385ea83b8e 0 -/usr/lib64/erlang/man/man3/ssh.3.gz 0d7408b947c45834a81c9a2620c221136cfbfc18b3e43b825d5aaf6aa099e3ea 0 -/usr/lib64/erlang/man/man3/ssh_agent.3.gz 49ad0bc88f149422c874382eb8590ff7f61e130c799976d43951413667017d67 0 -/usr/lib64/erlang/man/man3/ssh_client_channel.3.gz 37fc232ebacfed7a1c925b321ad8c72d464788d387d0d57436d04ed4fb5dd074 0 -/usr/lib64/erlang/man/man3/ssh_client_key_api.3.gz bd24f90ae2691146a1037e19e4b8950f313f35090e9fafd6e3ef056a9405d044 0 -/usr/lib64/erlang/man/man3/ssh_connection.3.gz 7bf3ddbc280b91ef50d6e2ab2a89a7529579905c4bd41912c5355f8e01c538e3 0 -/usr/lib64/erlang/man/man3/ssh_file.3.gz 8988bcfe43985eb08160485459accd11f4ff32f78971c91b44972f08c51e534a 0 -/usr/lib64/erlang/man/man3/ssh_server_channel.3.gz 89b82320718c89e9bbe4ee0b25347e46f6d8e02a5cadd7e2cc0a41a5cc383bee 0 -/usr/lib64/erlang/man/man3/ssh_server_key_api.3.gz bd1fa5225a2048bc2f7b042d3a1fd5fa60918ab0d31814687684af4e88f84443 0 -/usr/lib64/erlang/man/man3/ssh_sftp.3.gz c04d0e3b8c642863c2ca8320fa8afff683e60103b88d343c58e3573a75483933 0 -/usr/lib64/erlang/man/man3/ssh_sftpd.3.gz 67a085ac8a76a85bca6a5e2814c64270edcad88acbaf3e384d0cfd4cb6c7b498 0 -/usr/lib64/erlang/man/man3/ssl.3.gz a6649e559e4e9c83cf9e090df4468414680c4b15da5b10cf12b42c48123b3012 0 -/usr/lib64/erlang/man/man3/ssl_crl_cache.3.gz d702eb843eaf279534aebdb472f326052e6d3f7b13869cf59d167af7a7a26563 0 -/usr/lib64/erlang/man/man3/ssl_crl_cache_api.3.gz f9f404aaa7f9dbcc8078b815437a479680eb980a78a16a0ef2c24e1738894bc2 0 -/usr/lib64/erlang/man/man3/ssl_session_cache_api.3.gz 279db7f606d6ec8d788006dffeaf12fc7c9776afd302fdd2ffc0e20a09938b5c 0 -/usr/lib64/erlang/man/man3/string.3.gz 2db1d187f0d6a7deddb39d61dfb54547736a763cdec2e8f418849c77240da3a5 0 -/usr/lib64/erlang/man/man3/supervisor.3.gz 8e47d3e5909f6d6f4e21c92686771e3e7009a59d5c994ef02c2f704968d15a58 0 -/usr/lib64/erlang/man/man3/supervisor_bridge.3.gz 029da329e6c6b5741ff1dd4d8342eaef48f9e2f2dac11b9983cec79549be2705 0 -/usr/lib64/erlang/man/man3/sys.3.gz 925048eb224193a2783bc96e93dcb739493c59feed990715c2efb82574697c16 0 -/usr/lib64/erlang/man/man3/system_information.3.gz 5ada8b0799d4393104733bd11df8e89efbd1e344f8b1f8c36604a318411425dd 0 -/usr/lib64/erlang/man/man3/systools.3.gz 784756f0dcb817ff85c14c308c3de831906d4765c5b34fc0e33b95725cbe8cb7 0 -/usr/lib64/erlang/man/man3/tags.3.gz 0aec91ed817578a5f36a66aea43b6721a319ebfa687e5b6112341f49d77dd009 0 -/usr/lib64/erlang/man/man3/tftp.3.gz a8112b7d1bea1c6b913e81add4947ffbccc9b31d506d815e60615bb6642d9dbe 0 -/usr/lib64/erlang/man/man3/tftp_logger.3.gz 05477c5fd041bc34c93ef2ef39fbbbf5fb60009d93b0f613c7d71deb56d648e8 0 -/usr/lib64/erlang/man/man3/timer.3.gz 13e6fed2d3ff9417a3996c091870aaecd6c995fc326ac66d03615169f15b813f 0 -/usr/lib64/erlang/man/man3/tprof.3.gz a1950a1eb549148f33b6c9de4e92fab7cc128886942758e910eb2a5839556c44 0 -/usr/lib64/erlang/man/man3/trace.3.gz a144b4879e8c785946ee4d5adff08018e42c9ea95b03a128b27c24c6fe6e4658 0 -/usr/lib64/erlang/man/man3/ttb.3.gz 28fac02e57b8f087453caeb65779c095c30152dcf8ce6752536c7917a70daa8f 0 -/usr/lib64/erlang/man/man3/unicode.3.gz 6a62a52f251becf3325bbc1e37eabaa8942271792c4b8e617ae3e937751df53d 0 -/usr/lib64/erlang/man/man3/unix_telnet.3.gz 2aa044898d77086e13cea33481afd076b79b06ca0534c544c64d354370d67452 0 -/usr/lib64/erlang/man/man3/uri_string.3.gz 5f391316c467e35dd00a0ad38abe56bbed8346083557572ed5415252cce7a32f 0 -/usr/lib64/erlang/man/man3/win32reg.3.gz ca0b99ce734cfe7293bc0102b035433133ca1a4ec26028ab165054458ed811c9 0 -/usr/lib64/erlang/man/man3/wrap_log_reader.3.gz 7db7039201f1945c27ac8f7d4c28ce093b3698dfe43dad07aafcd7cbd64272f4 0 -/usr/lib64/erlang/man/man3/wx.3.gz 46e5a3ad58ede5f687fab87ad0b8695b0e7ee339ca7d1e29a38fdd13a9a729e3 0 -/usr/lib64/erlang/man/man3/wxAcceleratorEntry.3.gz 9eca6a9e7471aff32d3e4fe8fb745cb0af0e16aebb35a19be940511f6ffcafc2 0 -/usr/lib64/erlang/man/man3/wxAcceleratorTable.3.gz 43d81185417ff7762d085f5ca98d34f4b077e78cbc65fd9d45adcfc9a278867f 0 -/usr/lib64/erlang/man/man3/wxActivateEvent.3.gz add5c24670912723445b936d5c2e6160624196b6f4b03296cc56a262fb025994 0 -/usr/lib64/erlang/man/man3/wxArtProvider.3.gz 828b70e0d2a6aab4a6e1de25b993fa1bdf5489d79e573a84160cd01397de8544 0 -/usr/lib64/erlang/man/man3/wxAuiDockArt.3.gz 912e5e3df758495e200ef9a378437bafb806b62cb710a43c45ccb8ca77db3d2d 0 -/usr/lib64/erlang/man/man3/wxAuiManager.3.gz 11cef6e96064b95146b062d79a40f7d637d6c0a0d0612cba15fd246b1a4db90e 0 -/usr/lib64/erlang/man/man3/wxAuiManagerEvent.3.gz 5dbb5f5ed56a3dfb83f5fbaf6c0e27d5d5503a05df1e592241064522bde8d295 0 -/usr/lib64/erlang/man/man3/wxAuiNotebook.3.gz 1d2a120bd66325a640eca1e85cf0d7aa3ad5ef51a89c6929329e6a953b6fba5c 0 -/usr/lib64/erlang/man/man3/wxAuiNotebookEvent.3.gz 84b109a54f7fd0caee421befce1126d316becaa188a10fe88c04db44b729f065 0 -/usr/lib64/erlang/man/man3/wxAuiPaneInfo.3.gz 7c097b82e1eea8685614983d6c965e5b02092f6a2fe9219d83f808ba88ad3fd0 0 -/usr/lib64/erlang/man/man3/wxAuiSimpleTabArt.3.gz 34d9e0fadae4282e0d0da089728013395d509eae7962c95c240d91d2bf61ac01 0 -/usr/lib64/erlang/man/man3/wxAuiTabArt.3.gz 459e5ef91edab53feb4ae1b85c6f2d6c83fa84f74b25621fb4ce69807214e942 0 -/usr/lib64/erlang/man/man3/wxBitmap.3.gz c55c09b230dd87874b5e19b0c073a705ff66fb6a131d144182fb67ce6aef30f4 0 -/usr/lib64/erlang/man/man3/wxBitmapButton.3.gz 476723b114d1724ce73f3a65859b981af0c11fbdd16a6620e3f1b8fba2bc412d 0 -/usr/lib64/erlang/man/man3/wxBitmapDataObject.3.gz 6956a407a8be0eae054bcd75008ef5eb9a9bdebd0a3bb030065c97a2f610802d 0 -/usr/lib64/erlang/man/man3/wxBookCtrlBase.3.gz c34dab7e5f38967e38ea90da5ae0ae7bc2925e18896152cd803f2239bf915c8d 0 -/usr/lib64/erlang/man/man3/wxBookCtrlEvent.3.gz 192c826e136b951e4799bb02ee63f0667e70daff47835351c36f7c743a1ba56b 0 -/usr/lib64/erlang/man/man3/wxBoxSizer.3.gz bee8ffb36e7ea6b9b790a4df88fa2bf1d3c94d178e83cb857c6fc49b370928a4 0 -/usr/lib64/erlang/man/man3/wxBrush.3.gz 7cd7354aa39e9b98e42514f0a40881f372d95c490daf1b9a94567a2953d8b755 0 -/usr/lib64/erlang/man/man3/wxBufferedDC.3.gz 672aa87771bc19ca91a7753cc5aa50e6584c99dbd0e91f8869c48629a43515b7 0 -/usr/lib64/erlang/man/man3/wxBufferedPaintDC.3.gz 1bbb7a9220184359e3820470e45ce623c1a4cddf88a92920e8b84e27c33c63ef 0 -/usr/lib64/erlang/man/man3/wxButton.3.gz 7f6497cfa8913348b75fa5905022c5407970366415e41c8e775c02b0901ad440 0 -/usr/lib64/erlang/man/man3/wxCalendarCtrl.3.gz 10aa12a69c980ccde682d82a6d48e25ad146704d7497892f874aef7cd56a30c2 0 -/usr/lib64/erlang/man/man3/wxCalendarDateAttr.3.gz 7f15bf5e9e141a6a3b7aa4b49fe15352a028cfa6c1ea482fc2144a0b60425892 0 -/usr/lib64/erlang/man/man3/wxCalendarEvent.3.gz fa9d44061d339d273f1e575f290727cb9e172c4a0e06ad16cc9f884d762fbe2f 0 -/usr/lib64/erlang/man/man3/wxCaret.3.gz 0160fe343d87d962f169735cc4256f21618c6af2b7c7db6532549fde3f593cb2 0 -/usr/lib64/erlang/man/man3/wxCheckBox.3.gz 7d4db4382458f4b7847df6fd39ffbed6a2f0c7a96ddef458c3a4033bf31ef873 0 -/usr/lib64/erlang/man/man3/wxCheckListBox.3.gz 21ae64f77ba6f853435d1199d381905f785d9d21a517bec1cf598b2f71ad004d 0 -/usr/lib64/erlang/man/man3/wxChildFocusEvent.3.gz 70f1e532815c1ff35152c1ff5416643a9dc162d8495d3e579450c45267e0cc3f 0 -/usr/lib64/erlang/man/man3/wxChoice.3.gz c1ac7d3c4f398e439171c8fce6f4756f233731040b55e19e0b376446021f71c7 0 -/usr/lib64/erlang/man/man3/wxChoicebook.3.gz 542c8e703810da5c8db1d337e87d201242c036568dd6684387917cb92e6072b7 0 -/usr/lib64/erlang/man/man3/wxClientDC.3.gz df387fda4c3c4d3901343ae265dbc39fae239ffd320990261a5ed511171cba57 0 -/usr/lib64/erlang/man/man3/wxClipboard.3.gz 177cea5b5ce252fb16d84d87de0ace07e816ca67731fed3d90e062bb5aeea73e 0 -/usr/lib64/erlang/man/man3/wxClipboardTextEvent.3.gz f8e3c9e0c5dd169db00199e8b78b12e72c9ed32da8a1b42a5429b705e7938d1c 0 -/usr/lib64/erlang/man/man3/wxCloseEvent.3.gz dfa85f8a69b00011bee5d4429eb7d04f06322d5e774804a9f3fdee2099dc941a 0 -/usr/lib64/erlang/man/man3/wxColourData.3.gz 6819d700867e96fb0e3757f87cb88f6934ae20a66d89f8651d6ba2b0e65a19b2 0 -/usr/lib64/erlang/man/man3/wxColourDialog.3.gz c27ecdbbfdd3bac6931d2593cff4f03b3b6c1141d0d2ab20bb6d911ace42238e 0 -/usr/lib64/erlang/man/man3/wxColourPickerCtrl.3.gz e2d9ea1986a674294b86d65d01152eebb279ee6b0d3780f03357d074c63114d7 0 -/usr/lib64/erlang/man/man3/wxColourPickerEvent.3.gz 880c05cf5453fe1c96fb31aaa16eaaa77740b48a5a6cccc5d7053839fa5b4c35 0 -/usr/lib64/erlang/man/man3/wxComboBox.3.gz f464263ea72bbe3f7cdbd5aff81a30fab7316c99629b05a8539d40666e7feaa5 0 -/usr/lib64/erlang/man/man3/wxCommandEvent.3.gz 22424d4f2155280d8cc4ad28baf7b2f8ba12798460c88fc03619ba897595c0dd 0 -/usr/lib64/erlang/man/man3/wxContextMenuEvent.3.gz 5018f113c7f3183aceac8162174cdccb6d7500cbadc20147557807b09260c5d7 0 -/usr/lib64/erlang/man/man3/wxControl.3.gz 7bf04851e9c5e17261116e23679a69389ecd9ac9cbf02b07f8f511e135ef4286 0 -/usr/lib64/erlang/man/man3/wxControlWithItems.3.gz c0de5e437e8d001108ef5c9e8fb98d38e1140ee0a6d15e926a41affd901dff15 0 -/usr/lib64/erlang/man/man3/wxCursor.3.gz f4d5f4c6921fd4a5dd7208bbf4b104b130ace33369db8dd9cbb174039de409eb 0 -/usr/lib64/erlang/man/man3/wxDC.3.gz 0722f1148b7ae5d489d4aff7b93fda20f2149404368f10fe7e45178354a574d4 0 -/usr/lib64/erlang/man/man3/wxDCOverlay.3.gz b5311776f4a9b8f9cbbcb6af45b8f5fb327c00c4db4e7392952c72ecc23c63e1 0 -/usr/lib64/erlang/man/man3/wxDataObject.3.gz 6c441cad9bbf32bd9201f8509097eba4ba422901b96e9c05d1b0ef8d0faff009 0 -/usr/lib64/erlang/man/man3/wxDateEvent.3.gz 30e3017f10efd1f9953bf5576f66d0c546b49051738c35422285f870e1ac99d3 0 -/usr/lib64/erlang/man/man3/wxDatePickerCtrl.3.gz c095f76748036ec7311721bd4f8050c17b0bd3588ea34648778e6080cfc400fe 0 -/usr/lib64/erlang/man/man3/wxDialog.3.gz 1925ebaa8fc8956a33a983fac4bf9c1dc5e29c5d6c6dd7092c6c8f12c796cc92 0 -/usr/lib64/erlang/man/man3/wxDirDialog.3.gz be2d28a8d3832afc63c7e7796447883da3c2b060c1aebc862aebd344a213e546 0 -/usr/lib64/erlang/man/man3/wxDirPickerCtrl.3.gz d4c99a707953e2d7b6fff51313931db3f5b86cbb5cec3fd6c3afe6393d63e39a 0 -/usr/lib64/erlang/man/man3/wxDisplay.3.gz daed93af6c033832026a569313cab26d93cfa62374fa21ebf37380bef8e97fa1 0 -/usr/lib64/erlang/man/man3/wxDisplayChangedEvent.3.gz 1acebbe943eeb8b91a5f1d2f2eb33c7306e1481d6ff3b7c1b57360a20434ed0e 0 -/usr/lib64/erlang/man/man3/wxDropFilesEvent.3.gz e933ce1727c56c6640d313c34b8fe3b3672dbabaa05774a82a6e93b322e2805a 0 -/usr/lib64/erlang/man/man3/wxEraseEvent.3.gz 7dd59a414b3ae1a12ea0f7270a0b89043c9218ba208b49a59438074cdb4eb16e 0 -/usr/lib64/erlang/man/man3/wxEvent.3.gz 31e51f6aacf0c37bc6793b2a23d809c7cf2c9f20ecbbccb5407de360e1001492 0 -/usr/lib64/erlang/man/man3/wxEvtHandler.3.gz c9fcb3c98c25718f54c3a5e909cb7922e0436373626319f3149aa5f488e328f0 0 -/usr/lib64/erlang/man/man3/wxFileDataObject.3.gz 2fe2c95412755f55ac0cddc71a3fdf607d328d45a2e7a1df5ea866076b40479c 0 -/usr/lib64/erlang/man/man3/wxFileDialog.3.gz ce4736dcd197f9d05cb0910714409ac89dd204fd64865de2460225ea62c599a1 0 -/usr/lib64/erlang/man/man3/wxFileDirPickerEvent.3.gz 5afe2be1c1a890cf0353f69f5199411d6de2c24af33beb35c9acbac08b683120 0 -/usr/lib64/erlang/man/man3/wxFilePickerCtrl.3.gz 26d6c09fc6f7f796699e6afcee708c4303bc28539a6de062e8b1b213a16df5d1 0 -/usr/lib64/erlang/man/man3/wxFindReplaceData.3.gz eae532b43726be7cc74ba3ebad2f22cd7410fde0be1c12329b4d23de16e7dad0 0 -/usr/lib64/erlang/man/man3/wxFindReplaceDialog.3.gz e22ba804bbc38cec425487475d0e9fdccc69862d5e9760360dcbecd7e03ab758 0 -/usr/lib64/erlang/man/man3/wxFlexGridSizer.3.gz 66e61c72da5507903f05386b546d141f173df32acb7eb6c0b7d5f246f68f4544 0 -/usr/lib64/erlang/man/man3/wxFocusEvent.3.gz ce4ddc561722c79bd80303c64dda4a53acef406af84e64e1001c0992798a7384 0 -/usr/lib64/erlang/man/man3/wxFont.3.gz a6dc604b6cfcce1478206e3ddf1cbd996c1ea18e261c2b6fc98678c475f971e2 0 -/usr/lib64/erlang/man/man3/wxFontData.3.gz 1418a779409f13019e50fa6b81760989738843d9af8ddf534db41ba9857714b4 0 -/usr/lib64/erlang/man/man3/wxFontDialog.3.gz e417b3ecf7c4a563e2bd39bd904d0e9db7e5e4559a89c7ee3f6d3e836bae6850 0 -/usr/lib64/erlang/man/man3/wxFontPickerCtrl.3.gz 859b748dc56d99416401a4bb12f8d3dedb803d418bcd3e1896a6c0a238fb9f4c 0 -/usr/lib64/erlang/man/man3/wxFontPickerEvent.3.gz 6607b85be1dd55d991fb80f0aad9189a134656e63277707c5090c6bb6d631ca6 0 -/usr/lib64/erlang/man/man3/wxFrame.3.gz 7f30b0d83bc39cc0b512501bd7b359ccd3271fbd06a1f678be60f97ef2e9b948 0 -/usr/lib64/erlang/man/man3/wxGBSizerItem.3.gz e5345135533c9b879731d0de37b29f6273bb12c19255d54865d3ae336bd6ccec 0 -/usr/lib64/erlang/man/man3/wxGCDC.3.gz 7374a0c5e853881f6716dc9c4ebd7c7aab9c9683a728e7db5aad7e2513fcb4aa 0 -/usr/lib64/erlang/man/man3/wxGLCanvas.3.gz 4363d21a9a5e6ba45ca15f7bf59efe26428645e33408cfade9af7feeea817be6 0 -/usr/lib64/erlang/man/man3/wxGLContext.3.gz e43b52e27790635e03e032c29b3b4001cb97466dad69238f20f8c569299840f1 0 -/usr/lib64/erlang/man/man3/wxGauge.3.gz b090d91531f5cd44ca43e72e429775b9701d09773657ffff89c812907052f3fd 0 -/usr/lib64/erlang/man/man3/wxGenericDirCtrl.3.gz 999869dc95bbe2b47e0aa9dd44f3e91318cae68d40dd9b569f1c2d9fdb9c9bf3 0 -/usr/lib64/erlang/man/man3/wxGraphicsBrush.3.gz 3576c4fdd7fadc82600f3d2c46ce1732da95ca2b4c0fd2e7a5beeb798bcff212 0 -/usr/lib64/erlang/man/man3/wxGraphicsContext.3.gz 015f7d97742997c43eddcf6dbf0586f8f525179d4dd3da655cc89a652bb514b9 0 -/usr/lib64/erlang/man/man3/wxGraphicsFont.3.gz 36669005c3ac5c17138237060a8cc94e28cb6085bf81d7f1af59494ba765d394 0 -/usr/lib64/erlang/man/man3/wxGraphicsGradientStops.3.gz d12160cd5e3f56455b7949a9ef6ce238a32c58fbf93c722560eecba491a7c931 0 -/usr/lib64/erlang/man/man3/wxGraphicsMatrix.3.gz e2d6290ef04bcb494565e5ac8bf9decab72a1e38b902075a31d4f7f8c10a0663 0 -/usr/lib64/erlang/man/man3/wxGraphicsObject.3.gz 98f467e825fc1bd6730a199c7963185e6fb456062bc58c018280d6a46319533e 0 -/usr/lib64/erlang/man/man3/wxGraphicsPath.3.gz 414b0811827a806ef397fb3c02e5c61f8386497466119235b50a42068acb0530 0 -/usr/lib64/erlang/man/man3/wxGraphicsPen.3.gz 2909897c4520bdf88c44bc6ce2ad95342ea0655bba37e8c78eb109c1b0b89408 0 -/usr/lib64/erlang/man/man3/wxGraphicsRenderer.3.gz 2722f7e702b52347ebd7eec0dc9fcf42bd53e4acd8fcfb4c6fea7f027f57cc05 0 -/usr/lib64/erlang/man/man3/wxGrid.3.gz 10402cf166c62497b510c8df089900b9f535a7cce561522cbd629c0afff90ca1 0 -/usr/lib64/erlang/man/man3/wxGridBagSizer.3.gz f64731486d7ae8eca06f21fd1ae411b3247d4787a34f7b631ebc36ec4a2e3822 0 -/usr/lib64/erlang/man/man3/wxGridCellAttr.3.gz 055d5784692913fa5c3322d13c93e632d2eb9bbea325e6e4456c5a894300691d 0 -/usr/lib64/erlang/man/man3/wxGridCellBoolEditor.3.gz 7bc12401f0b84e4cbea798b082ed05962ba9f4b615dcbac74193282d07aba1be 0 -/usr/lib64/erlang/man/man3/wxGridCellBoolRenderer.3.gz 1cfa374edaa1b6b50e7f59ad26fe7dbf5505df046962fe163171ed209f6a1b97 0 -/usr/lib64/erlang/man/man3/wxGridCellChoiceEditor.3.gz c042038aeeefd4824e3a0b4d2270619b4439520846248c12bbaace17dac6cab1 0 -/usr/lib64/erlang/man/man3/wxGridCellEditor.3.gz 31b7032ff87bc706a64a9aac6880b65104904f478c4b4bcb5f22e07354fc33fa 0 -/usr/lib64/erlang/man/man3/wxGridCellFloatEditor.3.gz cb0385dfbfcda0201b797864b247f0849d8df6c828b7be5c5591e6182d4474b6 0 -/usr/lib64/erlang/man/man3/wxGridCellFloatRenderer.3.gz 82f48678c8e843701cb83b9cff8e8ae606044a6d34a37b2342d3e76428656158 0 -/usr/lib64/erlang/man/man3/wxGridCellNumberEditor.3.gz 0fb4d74badd79921734478ef3802582e9c942f38a4250ef00f5232c5ab300233 0 -/usr/lib64/erlang/man/man3/wxGridCellNumberRenderer.3.gz d14ea87dd0222479abb55dc2b7bc9995636226bfb4e88a8c7c86502b84f1b65b 0 -/usr/lib64/erlang/man/man3/wxGridCellRenderer.3.gz 2054a2c4341fd867a283cd318999805024f520c282dc709b3a25d98ad3f019eb 0 -/usr/lib64/erlang/man/man3/wxGridCellStringRenderer.3.gz 09924f9b11d4f91d01521c2c786be6862212ae70fd925b98bbe6f629fc39df78 0 -/usr/lib64/erlang/man/man3/wxGridCellTextEditor.3.gz c4e151419b25070868312e3aa2edde763f74380c95bf592fa5bfb1c9f2a133e2 0 -/usr/lib64/erlang/man/man3/wxGridEvent.3.gz 2f608df963cc2585d204c35703b533e4ac1158a0e70821d0884f71f021ce1fcb 0 -/usr/lib64/erlang/man/man3/wxGridSizer.3.gz efabf265840030ea56ba437f75d9e3025b69866cad84fd7d3e9154922237e666 0 -/usr/lib64/erlang/man/man3/wxHelpEvent.3.gz 6ef49eef901383e3f534687566d49eec00e5f0e3cee034c4e3ddc5e2b01deaf5 0 -/usr/lib64/erlang/man/man3/wxHtmlEasyPrinting.3.gz 0c25a88d46f826a18416a5232cd2c651673d06a7c246d46680775e232b413b54 0 -/usr/lib64/erlang/man/man3/wxHtmlLinkEvent.3.gz 08575db38779a1bcf2178d76c20a8d4cb38aafd97df592fa37340ce9af5564e0 0 -/usr/lib64/erlang/man/man3/wxHtmlWindow.3.gz 647a9325dfca33c482aca706cff80f012f4e4facc2b087d892222ce076e33840 0 -/usr/lib64/erlang/man/man3/wxIcon.3.gz 7d919027538432989864234e514ba94609629dce54d65cfea5302e31f4dd95a4 0 -/usr/lib64/erlang/man/man3/wxIconBundle.3.gz 9cec2a3837ef327a27fb1bbb0ec31615498d6f97a3892f647febf54c56da8e19 0 -/usr/lib64/erlang/man/man3/wxIconizeEvent.3.gz cd590a07fee0ead269ac7f7fc3966bfc074634c022e93e21ae8437f64a2da443 0 -/usr/lib64/erlang/man/man3/wxIdleEvent.3.gz e5b47d4065606634298254a4e8cd4251ca9319d5710da41c9b1c17cc1cf2ca19 0 -/usr/lib64/erlang/man/man3/wxImage.3.gz c7ce926d28ecdbb7e4634c6fbf7a7ea85d7c2d5d8a59230f12e6d65654c4c969 0 -/usr/lib64/erlang/man/man3/wxImageList.3.gz 903b4e5d700c559ffb959071090c8f520b2d4939734d88a5d20a4c5457dad5a8 0 -/usr/lib64/erlang/man/man3/wxInitDialogEvent.3.gz 944c679c4f8ba9942e2b42711ecc78a964a4dae99b065ff3ebc96607451797be 0 -/usr/lib64/erlang/man/man3/wxJoystickEvent.3.gz ce3cb028d8c909444c052bbdadb152548e9c367835aeb9cf2e082b585915896a 0 -/usr/lib64/erlang/man/man3/wxKeyEvent.3.gz 875fb67d42eb36807b737a7927a7e2b54ca051571973e36b17cade66dd49fc43 0 -/usr/lib64/erlang/man/man3/wxLayoutAlgorithm.3.gz b0c226c6eb269c7910ed516b511bea9f151c2ece6a1fcc14e17322e199ed72b0 0 -/usr/lib64/erlang/man/man3/wxListBox.3.gz 3ffcb6eefafb6bb7373a65cc4f09f627c8470404a4a3e290fd2eb9c4741c27a7 0 -/usr/lib64/erlang/man/man3/wxListCtrl.3.gz 53aba69809796341fd0b1b1c12159ee80ad457840bfa948b073aed32fb40396e 0 -/usr/lib64/erlang/man/man3/wxListEvent.3.gz 474ab94e01cd02a408cef76a36082da50a6983174210869b58c247a162296165 0 -/usr/lib64/erlang/man/man3/wxListItem.3.gz adc80bdb743a052ccd00e0362c1b6ec1473a74ec75bee02f002845af4e0f1097 0 -/usr/lib64/erlang/man/man3/wxListItemAttr.3.gz 3f1253220d66b99b60bc138868eb4a00396881b09a079dff79d4d0a922464745 0 -/usr/lib64/erlang/man/man3/wxListView.3.gz 0256bdd48e3596be5c6e51124e5faccc258df66c3c110d0976ac6e52d63c75f6 0 -/usr/lib64/erlang/man/man3/wxListbook.3.gz e95358670a8e52b93dfaabc068c9d413f4167cd3c75581761b9ec83afef5e879 0 -/usr/lib64/erlang/man/man3/wxLocale.3.gz 3d73dd1151ea708309cdb6bb8ec0a6cb268bcb69d9d1e426346e653d5f55a325 0 -/usr/lib64/erlang/man/man3/wxLogNull.3.gz 02ea11a51177b3d8c7fac29536cf88e9c6eb3f2ef8ff6be13d9735baaf92fadf 0 -/usr/lib64/erlang/man/man3/wxMDIChildFrame.3.gz 2715a0999382af205d3d1d5880e4aaa06616b13a628f9aa4e6c8d2ff98d61461 0 -/usr/lib64/erlang/man/man3/wxMDIClientWindow.3.gz bedf08af07cdb1b5a4d7e445b61555f2d255023f940903e83a7d1fcf14520fa9 0 -/usr/lib64/erlang/man/man3/wxMDIParentFrame.3.gz 657a1a3b578e62c9eb63e2c99272c18f8af770e233983500947863d65e55150b 0 -/usr/lib64/erlang/man/man3/wxMask.3.gz 243ab6fbb289f5fc2546bcc496bdac7a0e69a1f36c7034243478762e4da774e5 0 -/usr/lib64/erlang/man/man3/wxMaximizeEvent.3.gz 63fb63839a14e9094159771f2fbe6535a35140b4445f3aa45054abbf8e9da755 0 -/usr/lib64/erlang/man/man3/wxMemoryDC.3.gz f06c1ee1115d2fb799c8cbe3a89b4c7f458f55699f305fb59af98c5bc6766928 0 -/usr/lib64/erlang/man/man3/wxMenu.3.gz a00707ed70ca5cb0e321983396a32a1c04af6c0d1fcbe51d5eb137d83f7cd600 0 -/usr/lib64/erlang/man/man3/wxMenuBar.3.gz 24f110439e3fe553e74f05b242076148fcbbe9824987e114b2dab09ae76cf73f 0 -/usr/lib64/erlang/man/man3/wxMenuEvent.3.gz c042e4236058b97782b7232b1683baf8d7efe64779f348b24c660b779e962ff9 0 -/usr/lib64/erlang/man/man3/wxMenuItem.3.gz 17e4c35711c7cdb20ee4cfe88b3707882a4ceb0cccbe8dd138a45b9bd3a602b5 0 -/usr/lib64/erlang/man/man3/wxMessageDialog.3.gz 8fef43fbfc669e3a86742b3e5ee293c57b35fbd1ac14cb09d7e21c8c1bdfbd26 0 -/usr/lib64/erlang/man/man3/wxMiniFrame.3.gz 976b2fe0f60b9fbc933a252ec81bfb3527dc5785343014a357db5e251cf607a0 0 -/usr/lib64/erlang/man/man3/wxMirrorDC.3.gz e16144dbd9f54e89d17d8513c0d77a310766196c4d6fdf08e1f280bdf05c6bb4 0 -/usr/lib64/erlang/man/man3/wxMouseCaptureChangedEvent.3.gz ecf0d93c4aabbc72ee3dfa86c650ac090790dcf1e1e0ebaca0a004cae95a042e 0 -/usr/lib64/erlang/man/man3/wxMouseCaptureLostEvent.3.gz 01693bc8920d5a9be853cdd5598d1d46d00f6e84b88445257458a077e3aba375 0 -/usr/lib64/erlang/man/man3/wxMouseEvent.3.gz a103922788be369df1249a8d602e7155b8cdc674cbbcce062b7c2fb43271a23e 0 -/usr/lib64/erlang/man/man3/wxMoveEvent.3.gz 3e3f58f6241cd630d7c7cb0af2b43878109489173d2ca24fea3a4a13a04b2746 0 -/usr/lib64/erlang/man/man3/wxMultiChoiceDialog.3.gz bd8e29014ad1d31b6d1ba4846889838d7847a239174108def4e8abae8efb4908 0 -/usr/lib64/erlang/man/man3/wxNavigationKeyEvent.3.gz c968209afa62692c7ca43a80b3593e07e92c6d1ae87a70f9818e9fff9134c683 0 -/usr/lib64/erlang/man/man3/wxNotebook.3.gz a71dab2641476adef64ecbd7380b896382e34baa0870741314db1a2b93c5b05c 0 -/usr/lib64/erlang/man/man3/wxNotificationMessage.3.gz b836fb9ea3457aecaf5e298e396c6638972245276bf71cdce5ca65871e501bfa 0 -/usr/lib64/erlang/man/man3/wxNotifyEvent.3.gz 1f10745c130c4518d847db358580065e07b8582a250f32943191926521064baf 0 -/usr/lib64/erlang/man/man3/wxOverlay.3.gz ac706018c8b7ea58a93e20547eccb8d2ae8f899a357d0752fdc4bea7dbef1e1b 0 -/usr/lib64/erlang/man/man3/wxPageSetupDialog.3.gz f2f4e94043cc0b7569a9b0811e3ea858820e4c3e1556788a6d0a735011f70966 0 -/usr/lib64/erlang/man/man3/wxPageSetupDialogData.3.gz ef8bf203102adb2844fbdbccb2a9131c6c8ed8d21cb3b11051cabb4be809de70 0 -/usr/lib64/erlang/man/man3/wxPaintDC.3.gz abb9643913337d0e1e8088e10bca780ace0d0c42c229ec65ff29d82ab045f58b 0 -/usr/lib64/erlang/man/man3/wxPaintEvent.3.gz 5f5326c9d707a84889111df183f3b4efe1d1e34ea71a1a58011e3286d8299577 0 -/usr/lib64/erlang/man/man3/wxPalette.3.gz 5bc532f76cb3fc8c11fab752c5c0774a891f22b3ce4dd3b376482617d23da981 0 -/usr/lib64/erlang/man/man3/wxPaletteChangedEvent.3.gz 3090d70dd3249ab4bf0fdf51772e442882225b8fa4bb759be2ea926e0d4bf385 0 -/usr/lib64/erlang/man/man3/wxPanel.3.gz b74b61082d6306faff3fd33c23232a883026141863b057d4188e39544aed70fb 0 -/usr/lib64/erlang/man/man3/wxPasswordEntryDialog.3.gz 2f84fd70a5c07c74247bc0bcf34c6fcf8c0b91f6ab594637be2740117ea17f88 0 -/usr/lib64/erlang/man/man3/wxPen.3.gz 9d4c4462a063b9850a5bb070ff683ac8eb7670dfb276ec2e428973f8490e5fc7 0 -/usr/lib64/erlang/man/man3/wxPickerBase.3.gz 0e305499f09b3682824c79e44eda0c95e1f951af2c27d02889746f6a19fbbbdf 0 -/usr/lib64/erlang/man/man3/wxPopupTransientWindow.3.gz 8efa8b9ee6dec4d5612ef9330a1b65154237ff1ab94fcb840f967c8ac8cc7c01 0 -/usr/lib64/erlang/man/man3/wxPopupWindow.3.gz f158570f6decef9b0edd6facc66b022ea491ba99b3a521b5bcc7a7f39ecfe1ef 0 -/usr/lib64/erlang/man/man3/wxPostScriptDC.3.gz 290c7057466cc7ce419bb2dd98a5886754b04b21546a093d74bb5cfa7434de83 0 -/usr/lib64/erlang/man/man3/wxPreviewCanvas.3.gz e7526620964f5b23f939edaa0d5cef8125843896fc7a412e17a4efa40ea2f475 0 -/usr/lib64/erlang/man/man3/wxPreviewControlBar.3.gz 2130a4d614de5c8c17870468613c5ad690b5936da87cc09485ba1fac382c1992 0 -/usr/lib64/erlang/man/man3/wxPreviewFrame.3.gz e0c1bf9d45e237b5fa698af0834e9ab9ae4275f533fe0869c6bd0f8306761f88 0 -/usr/lib64/erlang/man/man3/wxPrintData.3.gz e2052b151148a1276eb10588d7c45093a111909dc0aaa675cfb73ff9d8324fb1 0 -/usr/lib64/erlang/man/man3/wxPrintDialog.3.gz 670ba393241c8aeda6ce0574ca9c115ac08a88832d063bf6c32d7025e4f33ce1 0 -/usr/lib64/erlang/man/man3/wxPrintDialogData.3.gz f03efef62a13e30beaf96fd3b8ff45207b765c713f28d9ed1c1897f9aed78a13 0 -/usr/lib64/erlang/man/man3/wxPrintPreview.3.gz 7b5aa6dc6c315e76d484179abaf9cc76639ec1afd98d403cbb92e8c2c8061df0 0 -/usr/lib64/erlang/man/man3/wxPrinter.3.gz d31452ae58f2faf4fb459a152bf3f8678237de1edf978fafa016f3a7c6fb1084 0 -/usr/lib64/erlang/man/man3/wxPrintout.3.gz 00869c89f47e8f8fc8812c35d58e8277bca203e2d8f71556a80cbaced3090f67 0 -/usr/lib64/erlang/man/man3/wxProgressDialog.3.gz 68a5788ef87bc1526c107d3e0f57b8e09273fc44ba7c3975f980cf96cdd91a6d 0 -/usr/lib64/erlang/man/man3/wxQueryNewPaletteEvent.3.gz 462b9309a66341266536337d2896cb2c0adb9179a84994859608abeed9935977 0 -/usr/lib64/erlang/man/man3/wxRadioBox.3.gz d759c0f119a55f2a174f08416aab01fd737aebc6beab8fa154bf93c58acefddb 0 -/usr/lib64/erlang/man/man3/wxRadioButton.3.gz 6102911e30ceaa268c74974a6d0f0de1f5ce7420486af33e7bf6ad124f42aa25 0 -/usr/lib64/erlang/man/man3/wxRegion.3.gz 9fc6695054012e9582e3061a74a9f17903deea57187852f5989329b5330b8333 0 -/usr/lib64/erlang/man/man3/wxSashEvent.3.gz ba67424ceebb22565fcfeb475a960078d9946c160167618daf9187b47ec7424f 0 -/usr/lib64/erlang/man/man3/wxSashLayoutWindow.3.gz 9a5bc7ef65b3dd8238d5c5cee75c7a20d53c408d31f939f868e486f042ea9ff7 0 -/usr/lib64/erlang/man/man3/wxSashWindow.3.gz e15a17eddaca071bad7d6e77fe798b9f9234498cfd2b1b2222fae80993450a96 0 -/usr/lib64/erlang/man/man3/wxScreenDC.3.gz 16154de5a24d5dc951e90f0bb69b5cf96bd9a15625b71d9a7b8ece170ffa2609 0 -/usr/lib64/erlang/man/man3/wxScrollBar.3.gz a8620127f12f623efbed1620f12437e2c8e2ce5aa75a66b59b5caac22a773292 0 -/usr/lib64/erlang/man/man3/wxScrollEvent.3.gz 34fed8101c0e0c230bd0c01b00da9124acd0fc9e59a6b94dcf6018097ecbf0f7 0 -/usr/lib64/erlang/man/man3/wxScrollWinEvent.3.gz 369ad73f204ae3426409869a59b66d900a16e322b7a3231901aecdf68e576a39 0 -/usr/lib64/erlang/man/man3/wxScrolledWindow.3.gz 81ac97cf2b37cb443dfdd691c13348edb1f67a3b8345954a4dc70198af9d879a 0 -/usr/lib64/erlang/man/man3/wxSetCursorEvent.3.gz 970852348263c487a6f5930e848cc7c245e948ca89631b5a284b4681ca5dfd4a 0 -/usr/lib64/erlang/man/man3/wxShowEvent.3.gz 43eb21b4dc5dba2507c20e2b6fbfd8924fee3093ec59f76022dc5e1559066eff 0 -/usr/lib64/erlang/man/man3/wxSingleChoiceDialog.3.gz 2e07c8a8e0482f1fc6ea7db6196b08fcecac1b83695639652008b7928a8ae743 0 -/usr/lib64/erlang/man/man3/wxSizeEvent.3.gz 5ee127a4e9acb6a0cf65b65dc099b9ceeb59f85de46e14556f5503e2ace6c7d2 0 -/usr/lib64/erlang/man/man3/wxSizer.3.gz c83acb1a7bea4052a0f5020546d1c40ef1efe2e211ee63ddef895760bd6e656a 0 -/usr/lib64/erlang/man/man3/wxSizerFlags.3.gz 39126621843f2108bec632f61fd64926ea39bfa76a97f1bd0b37ae8026ae553e 0 -/usr/lib64/erlang/man/man3/wxSizerItem.3.gz 29f0d4e97415188081f8c661252d3ccbadcb542ae19a4686d126872e93cfb945 0 -/usr/lib64/erlang/man/man3/wxSlider.3.gz 74022f6036a292ffdd1fbc8b3761f4079094db160cdad233f6b8794d3d8c7bd6 0 -/usr/lib64/erlang/man/man3/wxSpinButton.3.gz ed09403687250b805c40dc8bd39097f08d019dcde970c9dcd324c75d149c561c 0 -/usr/lib64/erlang/man/man3/wxSpinCtrl.3.gz 9797e3671db018880c0f66034be10f75ff385f1896efe1132f604d54d9daf9f1 0 -/usr/lib64/erlang/man/man3/wxSpinEvent.3.gz a982431d25cd1339235a18cf9dbceb958628d966a5cd2f6b895a71c8ea699182 0 -/usr/lib64/erlang/man/man3/wxSplashScreen.3.gz 08a881fd1277adb5744f4203f70166c9bf809b937a92161941e166fe0fcb502a 0 -/usr/lib64/erlang/man/man3/wxSplitterEvent.3.gz c16c3af6cee7b2ce73440bdadadd6765f0c31f602f7dfe0e77a021bbbf14ef52 0 -/usr/lib64/erlang/man/man3/wxSplitterWindow.3.gz fbfe186da50becb8ac78565b89a58027cb4f97cb2a5c03e3197e7237e9c58c0a 0 -/usr/lib64/erlang/man/man3/wxStaticBitmap.3.gz 67a4f4b9816fef96c8bb4cf4e6d9e29c484c83343a6a268326139a996627664e 0 -/usr/lib64/erlang/man/man3/wxStaticBox.3.gz 7f09d95dfba6fc64c3418c12157533d0d6252e633ede2424b7ca4f9b7a9a3d63 0 -/usr/lib64/erlang/man/man3/wxStaticBoxSizer.3.gz b851c6b7eed1ad070f24f46b5fea28af38749626f4721cc97f64bab38b358684 0 -/usr/lib64/erlang/man/man3/wxStaticLine.3.gz 11159e0f04bba79d079ae59ce19628ac0a3f01dbec675696e3ac52d1bb865252 0 -/usr/lib64/erlang/man/man3/wxStaticText.3.gz 5c66e6c52fce73e09c8ae93469fa26931d5fe80be7e3faec57f7e7602ded68de 0 -/usr/lib64/erlang/man/man3/wxStatusBar.3.gz 27e9889997307b7deb199c949fe4aabe31888de3085a10099fcb2b954c7a24c9 0 -/usr/lib64/erlang/man/man3/wxStdDialogButtonSizer.3.gz 33b0d8c7795f0f4e9b3296478bf4dab9238f3f307c78f0e93c1ff35d12548a09 0 -/usr/lib64/erlang/man/man3/wxStyledTextCtrl.3.gz 520b9bd0c6907e04194a28c41af146ed9033a73656e9dff54d6f8e651ba5020a 0 -/usr/lib64/erlang/man/man3/wxStyledTextEvent.3.gz 2c6d6edd37b0d4cf323702a47fe02fa13eb10004c23f8ed7e25a5e118899ab42 0 -/usr/lib64/erlang/man/man3/wxSysColourChangedEvent.3.gz 12d4bf8d80fc74d51fbc2cc08493254df11a52e84b14e03b52c2b3e168eb7b46 0 -/usr/lib64/erlang/man/man3/wxSystemOptions.3.gz ed9f7069fc6d94df5bdf0258bf4fb235533b594bd89f133c5b7d94ef50ba522b 0 -/usr/lib64/erlang/man/man3/wxSystemSettings.3.gz 8d8d1ca58a700fee6237caa59da840c07d1aa589623402fb7f9f68a9341c7d7f 0 -/usr/lib64/erlang/man/man3/wxTaskBarIcon.3.gz 423983355e42f032048d25d0812f7dedbb1ac492fd7e77498c0c9211ce21b94e 0 -/usr/lib64/erlang/man/man3/wxTaskBarIconEvent.3.gz 7224b7a513def4d8bb259bf66b571d54f0c11dfbff63d83ba7b89e257fab81c8 0 -/usr/lib64/erlang/man/man3/wxTextAttr.3.gz 1cd18eaebe765c53aa22cf9bf5683932241ff11be53022286e459056b7685f1c 0 -/usr/lib64/erlang/man/man3/wxTextCtrl.3.gz 7811b6db9fade24e63d0b68413638309627cbfb8f6a5844434c1252b99e7393a 0 -/usr/lib64/erlang/man/man3/wxTextDataObject.3.gz d9476eb567b5365ed88f0aecbbaf9261a97c0843894f4910f41efbd64b2b4e54 0 -/usr/lib64/erlang/man/man3/wxTextEntryDialog.3.gz 61c0f09ac7907d9fc0c10a4ec6bc2274b1244419e9953fdd0b286e2f582d87ae 0 -/usr/lib64/erlang/man/man3/wxToggleButton.3.gz 9ace6cd3c1df3869006cc2bc5a2df8ce9376ad9ea1d428aa1b6df00e99e386a4 0 -/usr/lib64/erlang/man/man3/wxToolBar.3.gz 5e290016456b7ddcade09cebda951669d004ce969553534c66ff4843a8b3d276 0 -/usr/lib64/erlang/man/man3/wxToolTip.3.gz 8cf4eabef5bcfbc52befef3067dfbcb2d31ef08bbb720aabc4227a5b2c11ae7e 0 -/usr/lib64/erlang/man/man3/wxToolbook.3.gz 58b017e2e50f64573ea2653462ba17b479bcfab80b713d210f056916718dcb64 0 -/usr/lib64/erlang/man/man3/wxTopLevelWindow.3.gz 9427955e641686f387f69bd7cd9a04706ac6d1b78792603e51e41b12dc1367f4 0 -/usr/lib64/erlang/man/man3/wxTreeCtrl.3.gz 1ca35b95a49d5282936c82acecfde49dbc8fbfc5e5937145c654834d22ba0b23 0 -/usr/lib64/erlang/man/man3/wxTreeEvent.3.gz a98a93d44f8d8b461343634003c309697ac2d9edc55f35530de62be4ca8fe1ad 0 -/usr/lib64/erlang/man/man3/wxTreebook.3.gz 34b06c009618f4aaa947ca2ceb086a26b2162b74d2bd500a6e10eee43ab51a28 0 -/usr/lib64/erlang/man/man3/wxUpdateUIEvent.3.gz a7861ea7299f1c362b292786d6ca6bcb322bdfeab7b0172e00ec357e741845c7 0 -/usr/lib64/erlang/man/man3/wxWebView.3.gz 22cc3970291a6974020b5fe7e7cd417daf716b46c537f08b728af7630f11296a 0 -/usr/lib64/erlang/man/man3/wxWebViewEvent.3.gz 23baf5b5ec52fb8c910d1748c7f433667da51ae5a954ccad2c50585c27b0a3fc 0 -/usr/lib64/erlang/man/man3/wxWindow.3.gz 94759d245c22dce1b665b8ccb4ff1f3ee58308325090c863c94267b39ce09589 0 -/usr/lib64/erlang/man/man3/wxWindowCreateEvent.3.gz 8125f46e166a5e3986ccf4bbb657067a7466676c887523b966cd03afaecf635d 0 -/usr/lib64/erlang/man/man3/wxWindowDC.3.gz 58280a66669fc1177b769cad0b31e0891c4968d2df208db4b591702578583deb 0 -/usr/lib64/erlang/man/man3/wxWindowDestroyEvent.3.gz f09ea6f01b0544b8621c87836c7bc1e1bf1956f9347ede7b341f8c95712717e2 0 -/usr/lib64/erlang/man/man3/wxXmlResource.3.gz 6651545826e5d6ca3d92bd323adba832a1fbd774f9fabe84ee47049090537837 0 -/usr/lib64/erlang/man/man3/wx_misc.3.gz 5a76bc08f56b2ef140c2fe47d7d9251cd2a2d71082f87af247fd4ef45f13d357 0 -/usr/lib64/erlang/man/man3/wx_object.3.gz 019b968b898f48da9f3763636e790c94e8f7e6ab22aa16e13d400f4e5075417f 0 -/usr/lib64/erlang/man/man3/xmerl.3.gz cd17d3a2654a9126ac87d9684bcaba0bd4a305be181735b7057650f4ba356d93 0 -/usr/lib64/erlang/man/man3/xmerl_eventp.3.gz 5e6827b0e30060a332aecee931b1069cc3d282381c6e908a0bc3ff87ce6ba616 0 -/usr/lib64/erlang/man/man3/xmerl_sax_parser.3.gz 4fc16176dd7d2d311bff51818bff648dccad1bb5dd65d8a6eb1611bf8193727c 0 -/usr/lib64/erlang/man/man3/xmerl_scan.3.gz 46ed92254330124eb41548c13b39d498b86a738ceb5f3db89076f687e27eadec 0 -/usr/lib64/erlang/man/man3/xmerl_xpath.3.gz d52038fa5641ea5e8ff0a4f48a76b5845d4f53f693ee9d619b12aa7523fd30f0 0 -/usr/lib64/erlang/man/man3/xmerl_xs.3.gz 6e5572d2b8a446d5cbab7e3263b175ed6ad88032b90f33831e70dc262ad67d15 0 -/usr/lib64/erlang/man/man3/xmerl_xsd.3.gz ab88e6b3575d9c86620752180f6e856bb8afb75e4164cc94b8e0a4bb17bc38ef 0 -/usr/lib64/erlang/man/man3/xref.3.gz 876d1a45d0dd19e7a2d04d6ede0145e34cbad02ad1d1416a6afd1d0098af0cb2 0 -/usr/lib64/erlang/man/man3/yecc.3.gz b8229b852f69cc4e2bfa891a619c5abac151bf87b36490c02232c9a8c9783deb 0 -/usr/lib64/erlang/man/man3/zip.3.gz ad3c649fb82bd969efe566954ae4da3a138530018295cc6d2e2b5742cf1a8ac1 0 -/usr/lib64/erlang/man/man3/zlib.3.gz 0c29c6d7c7bb21cd6d8a32aa51210f043b77adfe5eb82a2f76be1281aedff41b 0 -/usr/lib64/erlang/man/man3/zstd.3.gz 7a05bfbb86db9fb572d4dbcd2b93430d86df826968eefd4365d302b715b7b2ad 0 +/usr/lib64/erlang/man/man3/alarm_handler.3.gz 467eba6ef722323fc93b65650f29f8ab582ced1e2f4e6f1ad75ad498910aac7e 0 +/usr/lib64/erlang/man/man3/application.3.gz 32e6af9039488d8f7882a83311e5ce799c9417dc1e9369222d05e34094e6cf0a 0 +/usr/lib64/erlang/man/man3/argparse.3.gz ac633ec146b8a6ace6021e9271b532221aecd37edc2872c9e3fb7620bc29c01e 0 +/usr/lib64/erlang/man/man3/array.3.gz 28ac41234b5d45071b390f1f500c8e14e8bddc048174a8bb2dbd552a8abd128e 0 +/usr/lib64/erlang/man/man3/asn1ct.3.gz d51b8ad71ce08d873b98f64bb6856c07e719236433ce28c904822553ee78e40d 0 +/usr/lib64/erlang/man/man3/assert_hrl.3.gz e95073c238de920abf10f00253ac9bcce0f55c23d2e53d0a5dc04b6de5cf0afc 0 +/usr/lib64/erlang/man/man3/atomics.3.gz 46c3b9e00ad36deb0657ec5903ea4a5e2a3effce3cb970c97d06b86d3a9c2c18 0 +/usr/lib64/erlang/man/man3/auth.3.gz 00703a858ab305b7c94bb40f3c68e787f6f29443a5829d7da79ca4c1761192ae 0 +/usr/lib64/erlang/man/man3/base64.3.gz 206b1f160281e79699986676872f37aac3c0725985cab36186ea7414f5acf2b1 0 +/usr/lib64/erlang/man/man3/beam_lib.3.gz 6d70b7e0e5d6e6450fbab6e914a5eed62441d3c303b7fdced645df6905ae2566 0 +/usr/lib64/erlang/man/man3/binary.3.gz 06649b6837e2c7e7b46d10418ad560ddc44a76bcb79b7091ceb3dc90d2743ba4 0 +/usr/lib64/erlang/man/man3/c.3.gz b28dd9c8104efc0ed4cea63a9f2952ede6afdce1a9eb0048a7fac99ab008d663 0 +/usr/lib64/erlang/man/man3/calendar.3.gz 0fccd4d4409095ad98739024fa2683e827b73145ebfbb1cfdd73f2a5c684b600 0 +/usr/lib64/erlang/man/man3/cerl.3.gz 81221c29e9f78f3772c26f913807a60756ef9cd806faada05b0db2966e5efca6 0 +/usr/lib64/erlang/man/man3/cerl_clauses.3.gz 83994afb684e52f57730636599d502d07ab1548b893481a75f5f565a0a8852b9 0 +/usr/lib64/erlang/man/man3/cerl_trees.3.gz 72dc0556add1717ab7d341c1c31a89458351e09af9d1b94a15e586d5b87f9864 0 +/usr/lib64/erlang/man/man3/code.3.gz c939e5e6b00517e56cb18c1cc4ec69e416b88553072fd208d727e1a1b747b5aa 0 +/usr/lib64/erlang/man/man3/compile.3.gz 0fb5e3e40e7162cac0cee6de8fb2de779389a771e966a8452f5404bd5ddfd5dd 0 +/usr/lib64/erlang/man/man3/counters.3.gz 45c4f6cd60103d7f8788fdd160840907875146b556aa2dd69851adaa6a9870b6 0 +/usr/lib64/erlang/man/man3/cover.3.gz c276c156b01f6e219496562144a133d4a8fc27e18e85c004ec6ee95711aaa95e 0 +/usr/lib64/erlang/man/man3/cprof.3.gz 3fbaf4e2455b3bcc3d7e531a56a5bb6188944284236caa21372ba64e8d2daa5f 0 +/usr/lib64/erlang/man/man3/cpu_sup.3.gz c439945b1b174559ac4eae9405299382284fa3b9f81f6cb2039d97f61161d371 0 +/usr/lib64/erlang/man/man3/crashdump_viewer.3.gz 3b2dcffd32f4b92a7a324741dd176b6f4f43b64ec34c44f2e008ff0cfb5123be 0 +/usr/lib64/erlang/man/man3/crypto.3.gz 51514021f1385f60a8f5a5e51dc14297a66fd7306afe959153b8abd710cdf1a5 0 +/usr/lib64/erlang/man/man3/ct.3.gz 651099c3b088c1a9b9fd83235f474c705f6576facdf20ec30e94ba3ae71549e0 0 +/usr/lib64/erlang/man/man3/ct_cover.3.gz c419af455f4fb8fa692c6d5cbd356f06b5c0f3a26fd72e04bceaa553a3c689b4 0 +/usr/lib64/erlang/man/man3/ct_ftp.3.gz dbac7b7d65ab236837b2f1b7abf3c102251842d773ba9260a2b294a66c900be2 0 +/usr/lib64/erlang/man/man3/ct_hooks.3.gz 55c1c5bb9c0c0e7824837a3eecfd08b5b26bc59c2f6b7827a3fc34f1041f7122 0 +/usr/lib64/erlang/man/man3/ct_master.3.gz 1b8396407ca9016d426867f2e03e7f49e90d89f13ed332538f31c8f1c8198775 0 +/usr/lib64/erlang/man/man3/ct_netconfc.3.gz 0cc77c0d674fe2ffc7b07d5c1cc715d99b75a7749b9ca976b06d90edb35b398d 0 +/usr/lib64/erlang/man/man3/ct_property_test.3.gz e79a33b9f2801cde691dddda614be0069a0552a78c254da3959fc02b24959383 0 +/usr/lib64/erlang/man/man3/ct_rpc.3.gz 5988bc92bd2bb11b9107eb085fa5ad979df3e59c9b5b4f477341925e0a4a0740 0 +/usr/lib64/erlang/man/man3/ct_slave.3.gz 13c5317191a199761a449c649cb6985b936134cba864058fddc98bbf58aa32f1 0 +/usr/lib64/erlang/man/man3/ct_snmp.3.gz 5530de634324760a92d450c0beabb04127b9c85062a25dc654e8068cf475a453 0 +/usr/lib64/erlang/man/man3/ct_ssh.3.gz 28861ab26a199df6f9cda6c3afb1820c130921b254f9a115e33a9b9892d9fdd7 0 +/usr/lib64/erlang/man/man3/ct_suite.3.gz b3cea344de3c926644fb7b3a87c4c10ce323885ece3f6be98bda46991e932386 0 +/usr/lib64/erlang/man/man3/ct_telnet.3.gz 79c8ac53ec2f12735c2f4193cce17774c31e6c78496768008eb74e9c8dfdffa2 0 +/usr/lib64/erlang/man/man3/ct_testspec.3.gz 9e5bc23e74b7862bf0cab207237a8bd5e6559736e135c0b99b25416becbb79ff 0 +/usr/lib64/erlang/man/man3/dbg.3.gz 5ddf28b819cc3992395d3e0e8e88f60b563aad18d96579cf8898be8873b7731c 0 +/usr/lib64/erlang/man/man3/debugger.3.gz 5c6f1dd04ed4897619252ed318407073cfb3604c0db13f5716fb8a92ca3046cd 0 +/usr/lib64/erlang/man/man3/dets.3.gz 9d745ba41b3ad8498815582d77f51d62d473127bf37c8344a792fc68a14742cf 0 +/usr/lib64/erlang/man/man3/dialyzer.3.gz baece8575e4618a48b14e2c5a9a8178f43748a230ffba6ca94caf104097ab474 0 +/usr/lib64/erlang/man/man3/diameter.3.gz bdc6cef1df2533cf1515ad1325efda42f353e016141d893fde8de918759fe3c4 0 +/usr/lib64/erlang/man/man3/diameter_app.3.gz f734646b7492af4d9407ace0881d0060b4022e36f6bcbedb80f49d8419c6cd7d 0 +/usr/lib64/erlang/man/man3/diameter_codec.3.gz 9cbe0e9868e047718bd7c793813ed408ba55acb04970c1c40af7fe0af3191a97 0 +/usr/lib64/erlang/man/man3/diameter_make.3.gz 98f67b96ec251e4104641c630d546909898da870e131083fb8cfa370b92f4395 0 +/usr/lib64/erlang/man/man3/diameter_sctp.3.gz 4a78ffe7d9f9a6b44160fb781e9a8d97a53c89c7c15847c4a150a14e26a9ecf3 0 +/usr/lib64/erlang/man/man3/diameter_tcp.3.gz 6ace70c66842a3657600dc8b6351b0089472ae3c536690fad442bf88b54e4b74 0 +/usr/lib64/erlang/man/man3/diameter_transport.3.gz d94889559517d12084b25f4fad8b9bd4b66e2101e42c61d29491b4f84fc1e7cf 0 +/usr/lib64/erlang/man/man3/dict.3.gz 3680622ca087bf7943b302c199de4d0263edadab00212dd8207f4444bff3bb1d 0 +/usr/lib64/erlang/man/man3/digraph.3.gz fdb2e38c5efc27b1f272fcf31b46aecd1766dcd4f176c47fc79f7380ab294f14 0 +/usr/lib64/erlang/man/man3/digraph_utils.3.gz dd6c8d1e4af9fdbf0db2ca5cb2f754d59e95916ad636c39d938dc756853cb781 0 +/usr/lib64/erlang/man/man3/disk_log.3.gz 4125f37d8a30d11d9c776b179b07c73e58a7329027f81117b74d4389db9870f1 0 +/usr/lib64/erlang/man/man3/disksup.3.gz 68ced0bad588e98f47b6f45e01731f216102d5c4e931f5f0a38bc8abd14c6e2a 0 +/usr/lib64/erlang/man/man3/driver_entry.3.gz 49f47de5e252e6fcdee2f1657875b67f33c7f2758993e4fea8247066f7f719ad 0 +/usr/lib64/erlang/man/man3/dyntrace.3.gz 1fef5352142780cdfda0a40049e0371734a9bb9cbfad2349d8a37ccef783a623 0 +/usr/lib64/erlang/man/man3/edlin.3.gz 2ebe61afb1a158dd1b2b67e6eb825fa4265af1f6299b6262ea64d461c6d4b955 0 +/usr/lib64/erlang/man/man3/edlin_expand.3.gz a234eefa0eecbf34f3abf982a7d8c949058013432b7e1caac1a9a33acd8da060 0 +/usr/lib64/erlang/man/man3/edoc.3.gz 02d602db4fdc72352434c80f41aa867752dc15b5c8bc83e39c78f9679151af74 0 +/usr/lib64/erlang/man/man3/edoc_doclet.3.gz fc0d3cfa3a580822c22769460faa2a3426f871896adadcea08d22b133adc02c4 0 +/usr/lib64/erlang/man/man3/edoc_doclet_chunks.3.gz 8f8fabb51d94bd6003e2f8ba7456076c552857aef768071d680a0682002a492e 0 +/usr/lib64/erlang/man/man3/edoc_extract.3.gz 9c0e6134ab901be2c258d509f94f78f57b465b6eeb7307f645ba960712eb814c 0 +/usr/lib64/erlang/man/man3/edoc_html_to_markdown.3.gz 22c2480b27d6a6fa23578b0ee997e6a41b1f62831e46d7e4de028a5f8f2181e8 0 +/usr/lib64/erlang/man/man3/edoc_layout.3.gz aa3a980d1cbde9c04ad2b9f03543e56e02109ddf333674a54fdc5940807571c9 0 +/usr/lib64/erlang/man/man3/edoc_layout_chunks.3.gz 7e69168971f2724bb7b5f79b5ce1674799f15eef98418805775bae834c9ea00c 0 +/usr/lib64/erlang/man/man3/edoc_lib.3.gz f3a06ffaec4802c32a7f655daf2ad7170e07e1d64943620f658863f6cd8e1b9e 0 +/usr/lib64/erlang/man/man3/edoc_run.3.gz fa5f819569bc768924fe1369272d017370039a50e081ac4e781c51b11ea02095 0 +/usr/lib64/erlang/man/man3/ei.3.gz 518ef6cb4b11e7eb990e8155e035b1ae53236e6b07a20e7e609ef16d815e58b7 0 +/usr/lib64/erlang/man/man3/ei_connect.3.gz 610714e87966a8a389b84359d8badc46ee4fe8b7c6b0f50819a982e382b16da6 0 +/usr/lib64/erlang/man/man3/ei_global.3.gz 96c7b9bf6d82d6f419ac325db9e98a88459659f83616e931947b33f7bda61d0e 0 +/usr/lib64/erlang/man/man3/eldap.3.gz 09097dea0ca084fed0ee9544c1b593313e799a6a1ffa125782eb9d96cbcdb747 0 +/usr/lib64/erlang/man/man3/epp.3.gz a98238e11f101c4594bc1f0723471f6c9273d336ea4e950f4e7003301d44a73b 0 +/usr/lib64/erlang/man/man3/epp_dodger.3.gz db305707c6df1ea9c43acca7c5d4566bb86fd96f23ebd327ac439033975a4363 0 +/usr/lib64/erlang/man/man3/eprof.3.gz f0b4de0a7636aeb727389c29768035c9ff848ffeffef1403ed120a1e0d85665a 0 +/usr/lib64/erlang/man/man3/erl_anno.3.gz ee02d4523275790d559b0cd75f1fed042cfb098cbb71d367dd2d3018c54d2454 0 +/usr/lib64/erlang/man/man3/erl_boot_server.3.gz 2e257276c413a359806bce00cb482f0bb498374f62409ea2ff4258d9d7dfa970 0 +/usr/lib64/erlang/man/man3/erl_comment_scan.3.gz e340100fe5ad07803efa18464b5918abe6d88344c46528a7d2ae80d246f8cc68 0 +/usr/lib64/erlang/man/man3/erl_ddll.3.gz 910b0ea70184bc338563c22e3ed88e39878f20a501df7515e4e4eb5d4aa9f748 0 +/usr/lib64/erlang/man/man3/erl_debugger.3.gz 6ca0cfff28ecb5108c7f7f6a3f1a610c51fa29f2107584e72d0a98f56b0e78c9 0 +/usr/lib64/erlang/man/man3/erl_driver.3.gz 2f3ff875f8ea56bd601c12f6eee5bc4020accb64a070ccc86d785e07cdc60c22 0 +/usr/lib64/erlang/man/man3/erl_epmd.3.gz 7b21dad7b04336fdd1d95acb41610c1559f1b4ff8072fcf5a8b7d34de9705f73 0 +/usr/lib64/erlang/man/man3/erl_error.3.gz 82fed2c50a06414158059f66ed839125978e1edac555fe38c12ffd3082221778 0 +/usr/lib64/erlang/man/man3/erl_eval.3.gz e3d018aba1fa44b87461d14d3484d2ee23f3abab1e06828c02648e7938fa58e7 0 +/usr/lib64/erlang/man/man3/erl_expand_records.3.gz d6d868ce5ce2158bbe22b9d74b2bf556c4685548ff05144198ba56a2369d3386 0 +/usr/lib64/erlang/man/man3/erl_features.3.gz 9a2c23edf9d723611762724133954332cab6fa5032158ecbb797de644d894d3b 0 +/usr/lib64/erlang/man/man3/erl_internal.3.gz a62ed46c5f42f309f8425b7af02bdd74e8dd53fed1b8ab26fbcfa892eff1ebc7 0 +/usr/lib64/erlang/man/man3/erl_lint.3.gz 8c8f3ea26113b3131b62b00e49824417f85bcc3ae77f07fd65e7618444e106c8 0 +/usr/lib64/erlang/man/man3/erl_nif.3.gz 67271fdb9af63811612f473b09bc1e7a1b36c5dde93a82547fda9be05ac6550a 0 +/usr/lib64/erlang/man/man3/erl_parse.3.gz 67ac5e890e236d94fabe1d298b78a5bac95bc1184f17bf1a357e4d754842d35b 0 +/usr/lib64/erlang/man/man3/erl_pp.3.gz 48a71dd805d9b7ee1f509581a9f1d69bf92301466819b0c96813ee089d6dec42 0 +/usr/lib64/erlang/man/man3/erl_prettypr.3.gz 9a4665e4d81b284d7a5c191431ccb719f90761963d9e89908225af8cf19c0b7a 0 +/usr/lib64/erlang/man/man3/erl_prim_loader.3.gz 4d92bef75ca95421d01655d26792c8bd31b0f36058a732893feadb50a516bcb1 0 +/usr/lib64/erlang/man/man3/erl_recomment.3.gz 74d7b3709ef026a64e615dd8663ddb94cc1fdb816bfd97658b0f2f0d247c7267 0 +/usr/lib64/erlang/man/man3/erl_scan.3.gz 340521f9ba9186d2f7c8efdfe12ce50412c8790b71c8ab56a23688665117d8a0 0 +/usr/lib64/erlang/man/man3/erl_syntax.3.gz 78f9e7a204b07fa44b33ad52446d330b300a9e2ded02e6e9fde470f22c884b3a 0 +/usr/lib64/erlang/man/man3/erl_syntax_lib.3.gz 03b7bbea574ed479eebe63051ff149118505fe55a031d1490673fc851a2687c8 0 +/usr/lib64/erlang/man/man3/erl_tar.3.gz 1d59b7dc45d973229e50e70f9788b82ca1db6fb211e55c3ebd53ad48ad54bd23 0 +/usr/lib64/erlang/man/man3/erl_tracer.3.gz c1cd8e33cb4c5a2d4855a86a773796a900a68ef810ecc7b77c1ea95cf2d7ed6d 0 +/usr/lib64/erlang/man/man3/erlang.3.gz 3105e1848e16ed1d4488ee20b8bbcaf5069a7fac598fb5b7e41a589c6ab63ec2 0 +/usr/lib64/erlang/man/man3/erlang_port_info.3.gz 4df40a81b61d9c1d9010ef6b3142ab544d8909dee8ad418520c53479b04ba763 0 +/usr/lib64/erlang/man/man3/erlang_system_info.3.gz d49fc72a137118f5a898b2506f7be467b32a93a3b2899589761edaf0c34ee014 0 +/usr/lib64/erlang/man/man3/erpc.3.gz a13e7fda5a90f126d0a65aa83d7c1219267e70de88521c0fc929c86c35947d4e 0 +/usr/lib64/erlang/man/man3/error_handler.3.gz 4152989c932b463dd42859bb93b734f73f27d92ec156b1c9ec1ca0206f648f15 0 +/usr/lib64/erlang/man/man3/error_logger.3.gz beec991254b517e031409563cc060d0592f6ccf283b1a210a942b6f3abeca6a7 0 +/usr/lib64/erlang/man/man3/erts_alloc.3.gz 692874b48c7a0636bdbd53a5ac6ff99671d445ede2e6c535cabed2e120a3c64d 0 +/usr/lib64/erlang/man/man3/escript.3.gz 11d9aa036eed90e386e1a0c4ee669e354a0ffe8ef7b634116fe6204525b2f5d8 0 +/usr/lib64/erlang/man/man3/et.3.gz 31f53a369888f7b2e7f3b399554fafabd483cb45b8f4fdc9013c3058b6445dac 0 +/usr/lib64/erlang/man/man3/et_collector.3.gz 8f0c91365391b93c9142c50cc93ffe28c64737ab7d7e77dab53c425263b21094 0 +/usr/lib64/erlang/man/man3/et_selector.3.gz a8a215644d6679463409f95193a2774032fb43e83fcd8a9e672f2db0f5a4397d 0 +/usr/lib64/erlang/man/man3/et_viewer.3.gz 3382a034282a6b343e334cdee88feda980d25bbb73e272086764616c875c03fd 0 +/usr/lib64/erlang/man/man3/etop.3.gz 6427ab05fcc6fdbe45e4ec453c2aee4f796c5e9d9bcf641a1a3d4f2d694459c9 0 +/usr/lib64/erlang/man/man3/ets.3.gz cc5cb9d34c2bdb036d04e80e43540920297d06a18eac9f9facda127ebb70c54c 0 +/usr/lib64/erlang/man/man3/eunit.3.gz f2ad0dec27265b79c36ab8fbe22fd1785c67024e50908534d618cbc7b76e817f 0 +/usr/lib64/erlang/man/man3/eunit_surefire.3.gz 27b7dbca312a5734622aa3b75a53dc8a7767b78c9b7eb9e21529fec7c6bdb66b 0 +/usr/lib64/erlang/man/man3/file.3.gz 505a65fdc9720be11e0ad7af6bab1ebde8f79a7bf448b5196539e625f20c74da 0 +/usr/lib64/erlang/man/man3/file_sorter.3.gz e1f39453166a1f5446f70f40d4df56daf5342cc52aa3fe1dec94d22f41272183 0 +/usr/lib64/erlang/man/man3/filelib.3.gz ae902ec8633018693e62d30c6c2d06075180ca4d4500a02bbb96afa72d71e514 0 +/usr/lib64/erlang/man/man3/filename.3.gz a6dd7f9b32cd31a7b9d95b6847779ddb5f05975a36000663b90d9861d81eb3a3 0 +/usr/lib64/erlang/man/man3/fprof.3.gz ef3c3ff51131aa1e7716be3b9313c8ef38f8a4b24344f7cadad57ee50df683ef 0 +/usr/lib64/erlang/man/man3/ftp.3.gz bd92fe88e647263a0ed272948da8039d7d376bf66c1b829df1b0f50dd5e84b5e 0 +/usr/lib64/erlang/man/man3/gb_sets.3.gz 04521d2a61da7fd8cf416833b2744cc51ae2d5af2342565bd9323435c640649e 0 +/usr/lib64/erlang/man/man3/gb_trees.3.gz cb3c90c4b361a3d96239fa094eb8cc54ffed29b8c884a675e11672eba818816c 0 +/usr/lib64/erlang/man/man3/gen_event.3.gz f2ec6ee5f92335a73cac5a8b3dc3210f591276a98c6d3184868fdcd99b71d2f8 0 +/usr/lib64/erlang/man/man3/gen_fsm.3.gz 7ff3f8453c0c3b0a19699f03ef1ea6361c167cb14ed58f7d14c60d1e62021438 0 +/usr/lib64/erlang/man/man3/gen_sctp.3.gz 0dc0aea44e56edbd2fb5ece96160a42c2e1263a14daed75126eaaab2e5f40aca 0 +/usr/lib64/erlang/man/man3/gen_server.3.gz fd67a44cab465dfc870d0556388bf1250aef49e1ab223f5850a55536476f13ec 0 +/usr/lib64/erlang/man/man3/gen_statem.3.gz 79feb1f32070ca5f7a011644c976a7c80a5a7aa37f6bebc28267253a12f27588 0 +/usr/lib64/erlang/man/man3/gen_tcp.3.gz 38d140eb935eda3621bfb2f90f65e5ebb709f2f5d4d73899c6a57ee5c60325b2 0 +/usr/lib64/erlang/man/man3/gen_udp.3.gz 091c3c7689d7899e1f19afd83bdb4a7c9985898553ab7171f798b2a3090e0cd2 0 +/usr/lib64/erlang/man/man3/gl.3.gz 56305b4a2be39174f1c208402dfa68721a7209f0e8987f745c35dacba929a364 0 +/usr/lib64/erlang/man/man3/global.3.gz a3690442d0c464f4bb6f2453408d87057eee8fd040d56af808ccd1f30aa46b3f 0 +/usr/lib64/erlang/man/man3/global_group.3.gz cc9c484a10bb6d8d2f1a4322bdd48ca820ff27b39b8e88ec1854f9681604cc56 0 +/usr/lib64/erlang/man/man3/glu.3.gz c7184e334829a04da29d8324cf29e8712509a16435450474f8c9f7ffd8185e9c 0 +/usr/lib64/erlang/man/man3/heart.3.gz 06a5122c50e23f533f7de282aa4a1491f36ae3885b1db1cd28e723de50815019 0 +/usr/lib64/erlang/man/man3/http_uri.3.gz 5372d0573d88c27b7f7dc621fca01709098945d2d8b7061eda5db146886babbe 0 +/usr/lib64/erlang/man/man3/httpc.3.gz 8d62c09dce8839a78023e2f8b6a2f22c788d85300a96ca378632ca4f06c03595 0 +/usr/lib64/erlang/man/man3/httpd.3.gz ee95479af9b54d9f7d4edaca5ad6ce51449e0163a9a074255ad1e6a1e0233cf5 0 +/usr/lib64/erlang/man/man3/httpd_custom_api.3.gz edf1a5a9b3ad51bd61e2f23ba6462d8a049de0068fce6854baf298649ff1b6b3 0 +/usr/lib64/erlang/man/man3/httpd_socket.3.gz 0e26673b349bcafe87d7d5c8d3fc50accdb594dd6f929003a09485cce9dba22f 0 +/usr/lib64/erlang/man/man3/httpd_util.3.gz a43ad7e8029b271931d4ab20d1c690fa4f4b6d8118788981500aac60a8e3d537 0 +/usr/lib64/erlang/man/man3/i.3.gz c4f87014fc5a9fe818652b899ec59ae17ebde10bce2e4f1c695dc645c3c2d634 0 +/usr/lib64/erlang/man/man3/inet.3.gz aa6dad665a27480b4351aaa74b09e1c4b15fe74c75a3c21c16a55d0d172ac4fb 0 +/usr/lib64/erlang/man/man3/inet_res.3.gz 9c3d8f06feb82561946a2a11e66b53b03507d2377fef23b5813f6c0eba2b9603 0 +/usr/lib64/erlang/man/man3/inets.3.gz 9b2835e4a12ab29158daed9edf0f14bed199f3ddb2f8e1c61f1c0cc488275eef 0 +/usr/lib64/erlang/man/man3/init.3.gz 4d3c46b8506458d0ee60ac0e0ecd6bcd9353499aad99eec0b88c56270de39fdf 0 +/usr/lib64/erlang/man/man3/instrument.3.gz a089278d9a50aa2b035a53b48e53ab993d87d75524a6724d73e66906a560263d 0 +/usr/lib64/erlang/man/man3/int.3.gz 927996d1b2759a2ec5ec73da5dbc07aa806907efa98488af1fb9ec1f7e2cff16 0 +/usr/lib64/erlang/man/man3/io.3.gz cc0bd3766babaf8dadb16a21c45e8043e6861301782b865acc822f12355208ce 0 +/usr/lib64/erlang/man/man3/io_lib.3.gz 1badf0afa6a2d79bf0b2e3bc25739ffb5e656df05f0ae02b0fde4c6b0dd14aa5 0 +/usr/lib64/erlang/man/man3/json.3.gz 210e6b62cc31cf49067cd7b4ea77a7e5841080f240a5b834633bf504c37f454e 0 +/usr/lib64/erlang/man/man3/lcnt.3.gz 271fd57e6290c4db13b6a37aed28e4bf40a26777d13777113d8aae76add6bec6 0 +/usr/lib64/erlang/man/man3/leex.3.gz b0e4a51ce13f917bffe875e7b2500d37fff4ed166b0182e3a6de4716f2f61aa8 0 +/usr/lib64/erlang/man/man3/lists.3.gz ec0e6d581372fa791d08a20dc53c31a8bc254a0744054f1c7e6a89cd7d25617a 0 +/usr/lib64/erlang/man/man3/log_mf_h.3.gz 7c15799fd09964956c8f3ed0a3863505cf939f3c4df9ef2021882e338cec99b6 0 +/usr/lib64/erlang/man/man3/logger.3.gz fd6639951d60b924dd5058c3622fccfc9df68beec00051a0a6b5eab3c78e4150 0 +/usr/lib64/erlang/man/man3/logger_disk_log_h.3.gz 1ffef3ae6d1fdfc613d50089fc1c34863de8ecb3fae2d1594554187225d79d8f 0 +/usr/lib64/erlang/man/man3/logger_filters.3.gz 1170bdf0ad6842e7176d3e556731625886050540cca5c537fb5c9a5e68b7ffb6 0 +/usr/lib64/erlang/man/man3/logger_formatter.3.gz fc5bec855e75aaac34a35546f816a5af505a5c9a7cd0932c243ed1b62b0b0243 0 +/usr/lib64/erlang/man/man3/logger_handler.3.gz fc2c19b8d84cd87dc469d3ef5621ea8b9d4032ad54d0405e12aa061ea8e3e80b 0 +/usr/lib64/erlang/man/man3/logger_std_h.3.gz 880f29807c7c66c943447847185d6ea9c340a4223dc12e7166ff3f49b7254c99 0 +/usr/lib64/erlang/man/man3/make.3.gz b74fd0a100373d540ecc19a98f419ac646a705b6e7ec5c80736aecaff9788c75 0 +/usr/lib64/erlang/man/man3/maps.3.gz 60ccd62ce7e89dfecb5b6f859cc65c51d2599ef1f0b4db14c7237ea627faebe2 0 +/usr/lib64/erlang/man/man3/math.3.gz b0ed9388c55bc16e0c89a7520876bcd4d63949e5e15101beb8f9064144a4071c 0 +/usr/lib64/erlang/man/man3/megaco.3.gz 170957611e612f52e520f72d1833a8340d76d12fb277f1380e6ba06ca1ed171f 0 +/usr/lib64/erlang/man/man3/megaco_digit_map.3.gz 5d9918467d5db899e2b3c3b77693018e8a66056469af6b007edffeb716dc8daa 0 +/usr/lib64/erlang/man/man3/megaco_edist_compress.3.gz 42c9b2f021519ef564863b6a4db00ed0762f2824e946ccabd645ace4dd63e8df 0 +/usr/lib64/erlang/man/man3/megaco_encoder.3.gz d5c8551e1dba260635e99429e0f6c20b1d1e06977d69641ef09165d4d7a032f4 0 +/usr/lib64/erlang/man/man3/megaco_flex_scanner.3.gz 4c166ba835140a35fac0a09f08cf60a73023998494e1d6cd1cd76bb8442e99ff 0 +/usr/lib64/erlang/man/man3/megaco_sdp.3.gz 72394c2794faac7bb8dd8eedcfbcaf2f4dde4dbca0bd11fdd126bed1de613773 0 +/usr/lib64/erlang/man/man3/megaco_tcp.3.gz c01693c3e33498d0e5698816b6cb9fb28e55a338d29ed256a0f4ee92b4fb257c 0 +/usr/lib64/erlang/man/man3/megaco_transport.3.gz a14df345c50225d8e2c99d629c25bb4028cdd93c067ca04d0822283068de6ded 0 +/usr/lib64/erlang/man/man3/megaco_udp.3.gz 795a0051bad480acb3522a061d899386367871234f7cb252974092e492f86811 0 +/usr/lib64/erlang/man/man3/megaco_user.3.gz b6764382b8f444dbad03ec6cd94750bce7e168f7d69793506edbb3a77f74eb44 0 +/usr/lib64/erlang/man/man3/memsup.3.gz 65cfe1dc47bff786261ec96d4afa90b88f558c4298f351877d43dab7083cb278 0 +/usr/lib64/erlang/man/man3/merl.3.gz 5b37da5bcee892a088d8e8126dc3e68b62f8ba67347c41555cf39a38296cc221 0 +/usr/lib64/erlang/man/man3/merl_transform.3.gz bfb03fd5af5ff4b2df50f6e696df6ec28f2b5103b4fa79c54e623139cd5cd905 0 +/usr/lib64/erlang/man/man3/mnesia.3.gz f96420ed05369f8890d097d14d629952078e21e21ceb861edfa9e1aacdc8a07e 0 +/usr/lib64/erlang/man/man3/mnesia_frag_hash.3.gz 20ff57c9e866adaef54a49506f3548f33b028fc726d54ec334382a31758f0b2e 0 +/usr/lib64/erlang/man/man3/mnesia_registry.3.gz d0011c4729395193560d86dc5611c4a7aaaec43e28e487ab6d545c8d3410f82e 0 +/usr/lib64/erlang/man/man3/mod_alias.3.gz 8dada0ca85bf487339be54275f257696fa474838dd973ed007a6c074c0699579 0 +/usr/lib64/erlang/man/man3/mod_auth.3.gz f4b1f6ca8571c5bdbbb870b1d874282eb6e4aef06097285bdca0066fd82a20c2 0 +/usr/lib64/erlang/man/man3/mod_esi.3.gz 0beeee8fe210eaea77b09066105ce34ad9617c722b9738f885b5a60526022e65 0 +/usr/lib64/erlang/man/man3/mod_security.3.gz aa980b684be8f8eb8465c85aa83fd30e9b2ffbf3b176fdbd473f5be887df2c21 0 +/usr/lib64/erlang/man/man3/ms_transform.3.gz bbee5bb8182531142bd7fcb20b9b75f1cee6a42c712f2a422f421ab48699ef45 0 +/usr/lib64/erlang/man/man3/msacc.3.gz f3a3d4476b39ea6b4a1c8710f4fc5962566d7d8c8c503ee6e766c09650769356 0 +/usr/lib64/erlang/man/man3/net.3.gz 0372594c4cda1c2de2c831313a1dc8b50fb76d8a51f5660beed78f6ec18f75ef 0 +/usr/lib64/erlang/man/man3/net_adm.3.gz e1d9d8803f234f8a68182ca73272afaa88cc67066d17c7a6e8b25e362d8b8946 0 +/usr/lib64/erlang/man/man3/net_kernel.3.gz 4bf1fd65d600bec1282d5d265845a0582634997b7945555bd6a4f61a6497b480 0 +/usr/lib64/erlang/man/man3/nteventlog.3.gz 73fd8039bdb75f1f6a8a97c6d071ef20946579c0a774def09f610dddb3a36a93 0 +/usr/lib64/erlang/man/man3/observer.3.gz 2fd2c996a581e2c9fce0f5444268ea20f29a53e424f286d7ae2578333169a14a 0 +/usr/lib64/erlang/man/man3/odbc.3.gz 085409a516df2b13c393ac6b6af99e7248fc16f73c368480435faf9d36ef30e6 0 +/usr/lib64/erlang/man/man3/orddict.3.gz c0a55263a7fa7ba3f6bbb33d15e53e0ebf7f7fdfa285fcbd6be571d8fca09fc8 0 +/usr/lib64/erlang/man/man3/ordsets.3.gz f9541a70f2b0ae4630f1e4cb67798582c70eb35c45a4506300359c8b94826cc5 0 +/usr/lib64/erlang/man/man3/os.3.gz 3ebe94a9698a0fd66c8e37aaf2587eed7815ac92ef5fb2af25d69b4d0ffa3190 0 +/usr/lib64/erlang/man/man3/os_sup.3.gz d1bd87faca17447212ca061ed9f7465e088b11b48f160ba0a28fb914d4afeffc 0 +/usr/lib64/erlang/man/man3/peer.3.gz 11feb5f18bbe96a07d2263fc7bcff8a209cb6a231cb252b2ce2e91e060238808 0 +/usr/lib64/erlang/man/man3/persistent_term.3.gz 54d6d3eecf9371adda7d05219efb533c8a182d18e7294094d6253ffef1357bbc 0 +/usr/lib64/erlang/man/man3/pg.3.gz 8bc6f44e7c8b73d821d29e21a7b3df46f8f0a447dfef05f0c682fabefd642b5d 0 +/usr/lib64/erlang/man/man3/pool.3.gz 0c2ed5e5e80f7c356d19f5858d85eee98cde7d3d25be7ab333f701f7d57a8426 0 +/usr/lib64/erlang/man/man3/prettypr.3.gz 3237051646b9c861f9b93ee77a2dd052a29bd75d2c166172a2bcfe99c8ff6b25 0 +/usr/lib64/erlang/man/man3/proc_lib.3.gz d8d2bfde8823b08374c5bc6db2b465af6b9f0a8dd3edb25f6df5cd7cfd1c23f4 0 +/usr/lib64/erlang/man/man3/proplists.3.gz bd10839b55c8a4346c70c9e105b96bfc7e7a748371edb10b1845508ed33e7aec 0 +/usr/lib64/erlang/man/man3/public_key.3.gz 21b69e919e691752110a3452855f5b9461935f5391bfc9cdbb135d0190e9b282 0 +/usr/lib64/erlang/man/man3/qlc.3.gz e1868a07a7de0e0a278411094e833d53d6944150a3ba0d41d165d951efd890dc 0 +/usr/lib64/erlang/man/man3/queue.3.gz 426cc24c54aac06107fe23356da9f2d7261d1d5d92ce0e73078ced1b6e3caac3 0 +/usr/lib64/erlang/man/man3/rand.3.gz 78e19d2dc4fb6fc273c33c298b66cfdf5c0028d38ec5ec6b957df6a5042edd92 0 +/usr/lib64/erlang/man/man3/random.3.gz 3db8c1c477efe85b7c64238500c2f0c8fc7bd5862084ecfaf6d3ab72dd2c66a4 0 +/usr/lib64/erlang/man/man3/rb.3.gz b65bcaa0aba7f1efa98f47bc392b765bb8e091a4514697f28403801551b2fda5 0 +/usr/lib64/erlang/man/man3/re.3.gz 06ed790f3c856018690e1448448040f438f7d6884ffce14e790e97f19b98daa8 0 +/usr/lib64/erlang/man/man3/release_handler.3.gz cdf02d9c6f79e5f57d1bda2014bbac104592e477cfb25c38e1af4c7af63a0fcb 0 +/usr/lib64/erlang/man/man3/reltool.3.gz 0bed143ca4f9b3b13d01b96f58fac490d5feb5a86d2b4c91e2277fe3aa2da4b6 0 +/usr/lib64/erlang/man/man3/rpc.3.gz a913ffe3e728a3e9a1936e39fc11dcd4970f545239360614359e66c09aeda05e 0 +/usr/lib64/erlang/man/man3/scheduler.3.gz 8c8987ba71d4d2998f0e3f3de363d76b88c9201ffd74ddcef1d6dbd5743522c9 0 +/usr/lib64/erlang/man/man3/seq_trace.3.gz 7aa1f22f7b2b85c90f98c1c7bf00f36263779ec71bdbd58a0d17bcfbeca7e757 0 +/usr/lib64/erlang/man/man3/sets.3.gz 838ed89e5c33565aac9c176e78e07b110b851a194b7b086ce427108a32dcafb2 0 +/usr/lib64/erlang/man/man3/shell.3.gz 3eec5808a4e4dbcb28699562ee442e626fee203460afe84c64890e9ee670feeb 0 +/usr/lib64/erlang/man/man3/shell_default.3.gz a8cf61f87995085ceb23c0cdc85cfec20fca1e33aa3bda1457df00fc9639c181 0 +/usr/lib64/erlang/man/man3/shell_docs.3.gz 664a522e818a9b47600b2f2b5fa48de34f0277c4a8eaa10daee85dddf0a72966 0 +/usr/lib64/erlang/man/man3/slave.3.gz 3def76efe15704b1e951666bba6fdf0d2024d6012b2d2cc8d7a3fcd900b1f1e9 0 +/usr/lib64/erlang/man/man3/snmp.3.gz 2e0b1a146ff398199c337d4fc7b9f2c91cf48c1668990ad20cf2abed5702df54 0 +/usr/lib64/erlang/man/man3/snmp_community_mib.3.gz 95919eff9ef9fe2dd8a20476745ac1dff39e1338f79d8f477138d6b54f9f6cf1 0 +/usr/lib64/erlang/man/man3/snmp_framework_mib.3.gz f8aecbc8f0490e9837f59b7a05b5e9a87e77e1eb2a826fe1e22fbaa9525e4dc9 0 +/usr/lib64/erlang/man/man3/snmp_generic.3.gz 0dfc2dd51dea54f5b3025ac5ccb890dfae9de8ecec5d77aa723a56f98804f6fe 0 +/usr/lib64/erlang/man/man3/snmp_index.3.gz 17ead041bbb1164031938c79e9582311c011be02082e1e1d0ad3109ba848fad5 0 +/usr/lib64/erlang/man/man3/snmp_notification_mib.3.gz 3bd9eba518a6ad0a8556d2bc55a83f2dabc9367bc1e440f1f874d422964c77fe 0 +/usr/lib64/erlang/man/man3/snmp_pdus.3.gz 5c8cf6345a38ad94fc7526a8bd9790c12115e09bec197ea8d9cf1e4b771ae330 0 +/usr/lib64/erlang/man/man3/snmp_standard_mib.3.gz cfabd76fb944088f16e561a4e19d04d0d80b4e46f09329f6fa64e725781361ba 0 +/usr/lib64/erlang/man/man3/snmp_target_mib.3.gz 616fbc80baa120f714391b3fce01d49dc2e908ad74c7bd84c6b3d90be16d0ce4 0 +/usr/lib64/erlang/man/man3/snmp_user_based_sm_mib.3.gz b9b4a54280b88154f500dc180394f6036fdeb5fa3ae6e4411eddc179597418d6 0 +/usr/lib64/erlang/man/man3/snmp_view_based_acm_mib.3.gz bf7ddc34a06dce696329c09eeb76ef585854d63a12415780b88800ab4c71a5cb 0 +/usr/lib64/erlang/man/man3/snmpa.3.gz 0c08612882da2d457b99fc96e224ed2cba194693848eccc7d77b01627d494529 0 +/usr/lib64/erlang/man/man3/snmpa_conf.3.gz 88300ba2d1427906b3dde0e5eb5a7730d062022b43d0b62ec2ba8dcc70bcdb76 0 +/usr/lib64/erlang/man/man3/snmpa_discovery_handler.3.gz 890ebcef2a838675c43c87e8b739b03c867db2d0eaad053a29fd337697228ecb 0 +/usr/lib64/erlang/man/man3/snmpa_error.3.gz 2e81fb09ff6819bb57c5dd07f58be40c274a8c154ca16436af02dd96deb1baef 0 +/usr/lib64/erlang/man/man3/snmpa_error_io.3.gz 83b707d9b97ef7d5f9e1b22ecbb6e4688e474c800a16742e41f2c3e9e2dcfeea 0 +/usr/lib64/erlang/man/man3/snmpa_error_logger.3.gz 0ca8cda74b2b066e95ef94e39d662a4af4100cd84dfa637ff21ad3a5ebd879d8 0 +/usr/lib64/erlang/man/man3/snmpa_error_report.3.gz d8b4ad64f81fc203dfe96b5417f4c4cf094d250f79483afcc6193189c7db9f9c 0 +/usr/lib64/erlang/man/man3/snmpa_local_db.3.gz 891e2593ea0a5136e6ae16632eeeec70eacb17ddf89c21fd80775723e6166b55 0 +/usr/lib64/erlang/man/man3/snmpa_mib_data.3.gz 2e37d2baed00adcd367b008a8bad284cea8e5e3bb143b8ede6b3bc9f679bc2d3 0 +/usr/lib64/erlang/man/man3/snmpa_mib_storage.3.gz e141c9cafdc299610fc8a17a76b78ea84fc2bb0ac2c6c5c377b00a0fcaaf5f68 0 +/usr/lib64/erlang/man/man3/snmpa_mpd.3.gz 626c1dea3f7b1e960fd1f37db1fb9b570c16984a8325641e269d5f0bd26e54d0 0 +/usr/lib64/erlang/man/man3/snmpa_network_interface.3.gz ce73b9a56ac2389861f7815b9f8a2f2e83a2eceb20cd26a05547465a3df89276 0 +/usr/lib64/erlang/man/man3/snmpa_network_interface_filter.3.gz 3f150cc265e51346f64f00879d5043d804134fe584bf686819541dc4a7627858 0 +/usr/lib64/erlang/man/man3/snmpa_notification_delivery_info_receiver.3.gz 21dda3a3b744cc1afb8c4d19aa6a61bdcd79532d6b3ffef92946e8092c199de9 0 +/usr/lib64/erlang/man/man3/snmpa_notification_filter.3.gz 217316212397aefb8aa494ee0d046493fe028d16aff44fbe1913c520709fc98f 0 +/usr/lib64/erlang/man/man3/snmpa_supervisor.3.gz 71052e414fd80c2f6da428bfd5b80ba27cf50431abb1a064b520d919a67a12c5 0 +/usr/lib64/erlang/man/man3/snmpc.3.gz 8a473584ff6056cd4893860ac6f7d341cf3821b65a4f800386d3e4fdf2cdb10e 0 +/usr/lib64/erlang/man/man3/snmpm.3.gz fb0c10c76eb92ca47691fe8e4e92d4f340d4bde6e870859a091f727e5a241133 0 +/usr/lib64/erlang/man/man3/snmpm_conf.3.gz bd12a50b1fffb35121ff428cd523d806cbfa4561687df94087cd75c94d4e432d 0 +/usr/lib64/erlang/man/man3/snmpm_mpd.3.gz 02dd976b9928bc4f2ffb51509c2a5bc11386acbe2132b2920d627c6662b54f99 0 +/usr/lib64/erlang/man/man3/snmpm_network_interface.3.gz f9bd3fe84e521e644074202a28d788a0d2da58c98b4ae95bc73b4702567f0aec 0 +/usr/lib64/erlang/man/man3/snmpm_network_interface_filter.3.gz 6e3c31dbf2f903e44c627fa638c11cf584015a4ce8f587cdc46e50e35ff9ae9c 0 +/usr/lib64/erlang/man/man3/snmpm_user.3.gz b3b41aec391f01b858c9709daba0008f4992813e92f74520387c2f76015451ce 0 +/usr/lib64/erlang/man/man3/socket.3.gz fca224ec348a7be25168c66d224db3756c568a0fa182d0d74182497ea03b3d7b 0 +/usr/lib64/erlang/man/man3/sofs.3.gz c98d30c9e3df3b3dc3ae204baf3325b12f2aea68ff901bbf049eb6bc09e7475a 0 +/usr/lib64/erlang/man/man3/ssh.3.gz 628e482ccd2182ece0ed9693b5c37abc4db6a68c69216dce1ebef32fb61efe29 0 +/usr/lib64/erlang/man/man3/ssh_agent.3.gz 300c396d401defeeed9458acb806e1eb3899e96e27ab969d8bc66e3ca6394459 0 +/usr/lib64/erlang/man/man3/ssh_client_channel.3.gz cdf5b7485d989e56542c189bcbec27500414c40b443257dfe38d91c8da059ca8 0 +/usr/lib64/erlang/man/man3/ssh_client_key_api.3.gz a450d9aaf1f0884fc8c74706afacb61309054d9ed5f4898fc3975ef6a9aff49d 0 +/usr/lib64/erlang/man/man3/ssh_connection.3.gz 3627815c4183a4f5be165445fdf26678c5cc64530dce02e007b4c6e59e1cb671 0 +/usr/lib64/erlang/man/man3/ssh_file.3.gz 57a887c84bb83e9b5d21292faeb834023c9c7a00d63fc11b25cb2cf245261368 0 +/usr/lib64/erlang/man/man3/ssh_server_channel.3.gz 6abfd2790c2f91ee42ce0528fc8f069acb7e74df0eb168ddd4c1591456f139e2 0 +/usr/lib64/erlang/man/man3/ssh_server_key_api.3.gz c93d7b0b9976396ce4c63af87940efad8204e714549844ac79499ff0ca45564f 0 +/usr/lib64/erlang/man/man3/ssh_sftp.3.gz e7e91f622c73f7d0605e11800d041791442b0b88119b4eaf2cbbc62360917ea7 0 +/usr/lib64/erlang/man/man3/ssh_sftpd.3.gz 49d04e4264d1a3fae71920a08b53ba77f423bff6d46bbfc629e8fbaf77f658e8 0 +/usr/lib64/erlang/man/man3/ssl.3.gz ec21641545d05a228994f5b9c3de1a2a4359faa327245f3cbfd31223a9a9011a 0 +/usr/lib64/erlang/man/man3/ssl_crl_cache.3.gz f28030530fb06ca4926909cc852fd3f39287a61db867933f48faea018b86e80c 0 +/usr/lib64/erlang/man/man3/ssl_crl_cache_api.3.gz f411ca6186404d6778e9da62ed1eb4fc8aa36db1f56a23469243684337e81b52 0 +/usr/lib64/erlang/man/man3/ssl_session_cache_api.3.gz 3836dfaeabde9cc16dc58a1fe06e64c218294a6dacae5bd4d303fe4db7e8516f 0 +/usr/lib64/erlang/man/man3/string.3.gz 77aa736b04b034c56ff3d2f6a531b46b929dfee59e2bf536642b5213f1a9f06f 0 +/usr/lib64/erlang/man/man3/supervisor.3.gz d1b3d5729fb8daf478fc14a6794ef7ddfdc9c9f66022f1d2719623eebf391ed7 0 +/usr/lib64/erlang/man/man3/supervisor_bridge.3.gz e459f1e4574dc36f13b8abac7cc7cda73ea1c17bc1679597a17dea6cdc696023 0 +/usr/lib64/erlang/man/man3/sys.3.gz eca8928940d4fa1b9907a053183c86ceed56aff1b047df84046c70ca1ee8cb66 0 +/usr/lib64/erlang/man/man3/system_information.3.gz d40b8b692123185d521e3cf3a1397fcf488ed0fb99e2d7b92eaa5f92a9f72d5b 0 +/usr/lib64/erlang/man/man3/systools.3.gz 8ad73a8ab2118733112d1adee4ed19b29db2aafbe66140f5a04a58c74508b542 0 +/usr/lib64/erlang/man/man3/tags.3.gz a29edbc46fb34267f83b306d68ca3b11c9e72059d17ae0eecbfa41ca3205f8a3 0 +/usr/lib64/erlang/man/man3/tftp.3.gz 0beb74306a4612d4a40b8433d1e0a2ad915fcc8b820b3dd554fbc8d018a40139 0 +/usr/lib64/erlang/man/man3/tftp_logger.3.gz d3561500736875f250f21b530445d2ab649324b757a459e6f989fa8e0bcea946 0 +/usr/lib64/erlang/man/man3/timer.3.gz 759f5cbfb5d8fff3d8eb2b4e1c540bd6ae37d0937ef369a4298e9fd43758a520 0 +/usr/lib64/erlang/man/man3/tprof.3.gz 5dbc7dc146462a21498c5e511ed6d4100b1baa907f619a30a11f195ca1d03871 0 +/usr/lib64/erlang/man/man3/trace.3.gz 9c25dcb9bf4be17a13b88e101a52db81a8f4463e0c35e9c83f3b261eb19bb8bf 0 +/usr/lib64/erlang/man/man3/ttb.3.gz a3b4b50d37774179265bb555bb489f9d8e99458489e0f932bcfba60f194bfa7e 0 +/usr/lib64/erlang/man/man3/unicode.3.gz 9816cbd04d1ea9f9596f4ff1318a69da045eb56fb0faa65efe3c9bca1327a005 0 +/usr/lib64/erlang/man/man3/unix_telnet.3.gz 10062fd3d61bfb5d06e52b078f41c3dec86a46a56c3f6315b61ccbd330e56116 0 +/usr/lib64/erlang/man/man3/uri_string.3.gz 75598d5fd2a72d60c9b8f7d9c63dcb2daf979954e525221d3e6dd6601443e4d4 0 +/usr/lib64/erlang/man/man3/win32reg.3.gz a96e4acbf8002b16da799705c626d6eed0acff163da1d5c8a56c617ad84e7454 0 +/usr/lib64/erlang/man/man3/wrap_log_reader.3.gz bba19b411ac44c3cf1a5cebeff7df2f58e629708027e673d22c8f92f7684e26e 0 +/usr/lib64/erlang/man/man3/wx.3.gz a852a535b6000bdcdff454f15fa4f476d164e230aac82ccdd8f377f2cdfdd256 0 +/usr/lib64/erlang/man/man3/wxAcceleratorEntry.3.gz 19d1884579bd39382a9c702b4c0ab1649ce5b01e4682979dd153dcd7f2fca0cf 0 +/usr/lib64/erlang/man/man3/wxAcceleratorTable.3.gz 57c4fa069eac2c64cc29414a878c014284430dc5fe9186076e49553c88073be5 0 +/usr/lib64/erlang/man/man3/wxActivateEvent.3.gz 6de9df33338cde9f614e94f50a37d50ab9869363c4a964485a39fe4ddfcd3489 0 +/usr/lib64/erlang/man/man3/wxArtProvider.3.gz 6e3369b445ab74bb500f267676f7c6391bb83b3ebdbcf002003c1ace49f4077b 0 +/usr/lib64/erlang/man/man3/wxAuiDockArt.3.gz 92e61e4bd916f8b9bd5ec856de36b0ace20788dfc46c0fdc71bc19e04547fd2c 0 +/usr/lib64/erlang/man/man3/wxAuiManager.3.gz 469833846888e0530c3d373dde66ec8be69b3d43e396cff93168ce56985fa67a 0 +/usr/lib64/erlang/man/man3/wxAuiManagerEvent.3.gz b38a6010b9e9ae77a5d944ce4b0e01c55167abb52fd0f18a00adb573a540a63e 0 +/usr/lib64/erlang/man/man3/wxAuiNotebook.3.gz 80e7e86366ec1ac12d5e73422a4ec5ce36bbcf533124fa182aa6441547d5389e 0 +/usr/lib64/erlang/man/man3/wxAuiNotebookEvent.3.gz 4feebedfaf8f3c3b62034202c6898cbd4ebcf9f017ec835cc6217aad22d40233 0 +/usr/lib64/erlang/man/man3/wxAuiPaneInfo.3.gz bb752901f07cf97c711ffe242b55e4e4c03a8e22e9a139d536ff7a854b9697f3 0 +/usr/lib64/erlang/man/man3/wxAuiSimpleTabArt.3.gz c9508fe12e5c92429e90332d10cd55780b56cbe1a40d9d858ca0f8a87c551d9e 0 +/usr/lib64/erlang/man/man3/wxAuiTabArt.3.gz f13a3a50b75b94b624995e95bf43c45ca2b38bcf3285686eb82958ebecc455d4 0 +/usr/lib64/erlang/man/man3/wxBitmap.3.gz b5ed6ec814a77c3876d02ffa3a2e00b4a1e946264322640880990d76fca15ea8 0 +/usr/lib64/erlang/man/man3/wxBitmapButton.3.gz 0775323161895f47fc959f01204f2d7e0655ff47b13396f2a616947e600a6f85 0 +/usr/lib64/erlang/man/man3/wxBitmapDataObject.3.gz 10e5162f724d63661189e030c22a1b68b0d597bedd9e0a9da36f6b08c526a6bb 0 +/usr/lib64/erlang/man/man3/wxBookCtrlBase.3.gz 87f5a6c26c2c4cdcebbd8a43fde7f7229074d1ee380d31cf2a44e4a08a379072 0 +/usr/lib64/erlang/man/man3/wxBookCtrlEvent.3.gz 98975e54accca52bdeea7f5611d70d0af9985cdf8d4b6cd8ff1922907fa6d4b4 0 +/usr/lib64/erlang/man/man3/wxBoxSizer.3.gz 8a9d91712dcae44b596dfed49bb19d6eaecad70447dd1983c6723636ae253c98 0 +/usr/lib64/erlang/man/man3/wxBrush.3.gz 63b618b01de72dabde02178344fc907f3c6376edc3e281ee376eabd6cf234e24 0 +/usr/lib64/erlang/man/man3/wxBufferedDC.3.gz 1fdd8e982d2cbf71459a2ae2186937a14e420ae76e847078ea2f051e50acec26 0 +/usr/lib64/erlang/man/man3/wxBufferedPaintDC.3.gz 06ae30b416218c0bc4eaad38f95ff14762b1b273a0c501ae1f8ab9d79e0a09a3 0 +/usr/lib64/erlang/man/man3/wxButton.3.gz 937ced8936ef939b13b23078603404764e695da1d3301a8a0898d164327814fd 0 +/usr/lib64/erlang/man/man3/wxCalendarCtrl.3.gz 7e4d8dd6d1b621cd134b71e6671ccbbb94f8dfe4ccecc968bc6c9972b2908019 0 +/usr/lib64/erlang/man/man3/wxCalendarDateAttr.3.gz 1a0da81ef91ffaed489795573752d91e2b42ddad18b1cc7be11037d525d7660d 0 +/usr/lib64/erlang/man/man3/wxCalendarEvent.3.gz 14995df524e441de3854b42c9cc391569f6f30c796b9af6356b152eca5baf7e0 0 +/usr/lib64/erlang/man/man3/wxCaret.3.gz fd77d81de1ac0260cf8ff3a3532d01b2917e4fa769e1ae5854725bdca09523b6 0 +/usr/lib64/erlang/man/man3/wxCheckBox.3.gz 99e9e40fca542a6e0803646704e89c6967b340075097e3555f7e42e618c6e548 0 +/usr/lib64/erlang/man/man3/wxCheckListBox.3.gz eab6145a97af3b32318f1265e1ed424ea4c6770eb99a354811e1460b50097276 0 +/usr/lib64/erlang/man/man3/wxChildFocusEvent.3.gz 7572786e0f24ef9527d5cfb1ea749aee1e0e7a5a5503921e3fea7d3ebeebabd5 0 +/usr/lib64/erlang/man/man3/wxChoice.3.gz ea504a91727c0cab08f8c893c73edd8b8b46ceedfd9f3a4f72f77d7c77e200df 0 +/usr/lib64/erlang/man/man3/wxChoicebook.3.gz ac2142507cf7aa63408eeab9944a00e55f75f3c7bfbd8f91c52fa1a6e31fe6e8 0 +/usr/lib64/erlang/man/man3/wxClientDC.3.gz 5f533cd75dee1ae408caa40ced6a04960a24eee5bca969e55668bcbc50e5e639 0 +/usr/lib64/erlang/man/man3/wxClipboard.3.gz c132ede1d9c3dc01d6bb0c633b17ee24c8bc727ba09174fb17c6f844350b00bf 0 +/usr/lib64/erlang/man/man3/wxClipboardTextEvent.3.gz ec358aed842fd384483626739a58835f201e6e10db769a056048aefb50bf3e51 0 +/usr/lib64/erlang/man/man3/wxCloseEvent.3.gz ea0096e53fe0d5e92c3f2bb2a71b22cda8731a0b7253af0f9e9867060b988b05 0 +/usr/lib64/erlang/man/man3/wxColourData.3.gz dd3df415daedede182b47922266ffdaeb2845456ae4181d2ae223da583f48197 0 +/usr/lib64/erlang/man/man3/wxColourDialog.3.gz c80d4a2a4a84c136efad62fe67f254e6466de45f2e74ccb08c5e647478f5b9e2 0 +/usr/lib64/erlang/man/man3/wxColourPickerCtrl.3.gz ab475ac3263bcbadf41203930beacb4296e4fc28939f8866f17996d7f1fed815 0 +/usr/lib64/erlang/man/man3/wxColourPickerEvent.3.gz 7926961d4fb1034cfb3572890314171f681fea79795ef9f7e913e0e7ae17aa30 0 +/usr/lib64/erlang/man/man3/wxComboBox.3.gz ad5f7750be68509ec24b2beb4331a08758054a3ddb3fd91987fd916d8a359db8 0 +/usr/lib64/erlang/man/man3/wxCommandEvent.3.gz 3067737aeab7ab936a8a8ba1e39a916c4aab6f0ba6ec5db03c1eabb19e1b1b71 0 +/usr/lib64/erlang/man/man3/wxContextMenuEvent.3.gz 36b65d0bec0a2edcea33ddbd6f5ef9f735689213d69583a8e0170105d066233a 0 +/usr/lib64/erlang/man/man3/wxControl.3.gz adb4da5d3b582aea3cc0052b02e39c82c9ed07557570a909e7766059a3cc7cac 0 +/usr/lib64/erlang/man/man3/wxControlWithItems.3.gz 384ce05833339c71be9b8feed343b89b4875eebca1f10cf0a0a12adcd82e82c9 0 +/usr/lib64/erlang/man/man3/wxCursor.3.gz 8a0823683b874d9e8ab7da453aa48a3915a2d7071a1ef7486031b7febf024a9a 0 +/usr/lib64/erlang/man/man3/wxDC.3.gz 439886d027aecb8cbe27263c644e04508b0ffed9f06bb12535f0fa5081518b48 0 +/usr/lib64/erlang/man/man3/wxDCOverlay.3.gz cbd2be8f380b84f0e856fd9fde344b4decc225a5505277289d15139fd5e15413 0 +/usr/lib64/erlang/man/man3/wxDataObject.3.gz 869a9d08fde9049eb4751f16cc93cf77d5d5da4a9793e4ca5d36c76e6821bbe6 0 +/usr/lib64/erlang/man/man3/wxDateEvent.3.gz cd4510a83faa9a0a6de3927948931d167e71bb3b0ea54403e6c6c0660efba731 0 +/usr/lib64/erlang/man/man3/wxDatePickerCtrl.3.gz 8010c6c762599d61dc840f7667512f0c4a98e572312dccbc1681fa10340bac19 0 +/usr/lib64/erlang/man/man3/wxDialog.3.gz 2ab0dfc44979a53dbaad0c7166912aa31dfc9ecc309d3e1d63b6be4efe96caa8 0 +/usr/lib64/erlang/man/man3/wxDirDialog.3.gz 75900a9377e84de6a42a1d3d3808cd0efb85a2204012db1069974ada95eddc58 0 +/usr/lib64/erlang/man/man3/wxDirPickerCtrl.3.gz b0d693fee8695ed2d7e64c9ec388cdf68785f514fb5705ce78e4eba50b177c6e 0 +/usr/lib64/erlang/man/man3/wxDisplay.3.gz 0836e18459074d8dddc8ac35d459c3b4a8180e3024b10c966886f5b26eeca59f 0 +/usr/lib64/erlang/man/man3/wxDisplayChangedEvent.3.gz 64a489a057779c03814afc13fc39db0cb429ad0377b7164b0e50af8b4fbc9ea1 0 +/usr/lib64/erlang/man/man3/wxDropFilesEvent.3.gz c1bbf508e4d95f87196015755137dad6834d45bc0fbba439f021978c0a49ee86 0 +/usr/lib64/erlang/man/man3/wxEraseEvent.3.gz f711582ca2d1f86fd0452833d5e42fc8a3e22de54835ca6673bf361e33d114b9 0 +/usr/lib64/erlang/man/man3/wxEvent.3.gz 5d85f2e85cada87ed92aec347dfa65b1febb346a13654d24796f9ffd26586c19 0 +/usr/lib64/erlang/man/man3/wxEvtHandler.3.gz 0733049db6902b1db34c1bb92a4f7c7a54ed2270167ee598243d898bed4ea826 0 +/usr/lib64/erlang/man/man3/wxFileDataObject.3.gz 0f6bdc6c82fdcd8ee257164186651e2d168a32ce98d71041140e374fecb908d2 0 +/usr/lib64/erlang/man/man3/wxFileDialog.3.gz 326badee4190df32061d44eeb6d95f15e1e42b6cc7e0c778d9d9cf637f3f83d4 0 +/usr/lib64/erlang/man/man3/wxFileDirPickerEvent.3.gz d0c4a34f10bf2ce648262f672d6f7e79bcd2d2e66dc7d1ccf011dae25158a5a8 0 +/usr/lib64/erlang/man/man3/wxFilePickerCtrl.3.gz 475b10700fe86559dd89920d52e18b0246e449866b854ef34b4415e04b3d47dd 0 +/usr/lib64/erlang/man/man3/wxFindReplaceData.3.gz 8f221c7fb98b124a40085561e4d1dcf60c2f047cac8755cc4cc46a10cebd5dad 0 +/usr/lib64/erlang/man/man3/wxFindReplaceDialog.3.gz 88f051d66d86e682e9de4c55e04b1ec26deb4d2e4e6151f61d75407e4d8d4071 0 +/usr/lib64/erlang/man/man3/wxFlexGridSizer.3.gz cd905224b65e2c9850157756614c68c96c7a2885debb49d7c60459cffa6737e5 0 +/usr/lib64/erlang/man/man3/wxFocusEvent.3.gz fa0c54f68c419c1a162ebec986ed890c395a028075d83cb4f6b905cd13d70ac0 0 +/usr/lib64/erlang/man/man3/wxFont.3.gz 10287c5b2b3249754d548877028887edcf7562319aa79db7a1b7c787b7de3db5 0 +/usr/lib64/erlang/man/man3/wxFontData.3.gz 5120a94f16b32efbe86e40d7e494ae7e453caa426a6770c2ff9090cee865b5cf 0 +/usr/lib64/erlang/man/man3/wxFontDialog.3.gz 16194d55d0435723228b38a06e4693a849b6ecdb7efb3cf66d593bca7a6c0f98 0 +/usr/lib64/erlang/man/man3/wxFontPickerCtrl.3.gz 99b19ea9fcd6f4dcfbe5cf4926f274f5e6a422cc0036c99f0b982f34ea806e37 0 +/usr/lib64/erlang/man/man3/wxFontPickerEvent.3.gz f2a2c361d59c410b96a23583da3176906c4dd1d54ef86e0939eb893e29cb8a04 0 +/usr/lib64/erlang/man/man3/wxFrame.3.gz 590cf14191f11a6e1c00ba899843d7fbd2d3f62fe86e616e96964715ae35839f 0 +/usr/lib64/erlang/man/man3/wxGBSizerItem.3.gz 8e8cf76629fe7150c1a8bed52070272aa2fb0ba1efc9bf5a7de02c3185de4d07 0 +/usr/lib64/erlang/man/man3/wxGCDC.3.gz 377a650fe7541e1996adedcfc48735a266a551d84098077a1d9df0e8a84c8747 0 +/usr/lib64/erlang/man/man3/wxGLCanvas.3.gz 8732624c272e4c8899eeb7a9e1748e7b7015218aac55277a2507efcbe61d0667 0 +/usr/lib64/erlang/man/man3/wxGLContext.3.gz f43b62b3bc737fd20c962d60a92f893df4e4435c3659142c5e66d6a5937054a4 0 +/usr/lib64/erlang/man/man3/wxGauge.3.gz 9a32dbff14357a8c3d0afff6c6b07f8a9330549ccbdd55ccad6839896ca23454 0 +/usr/lib64/erlang/man/man3/wxGenericDirCtrl.3.gz 0e8bd1eea74b48cde6c4d13cda27839772d8df533a498c22d5cd4065d3afa773 0 +/usr/lib64/erlang/man/man3/wxGraphicsBrush.3.gz 54a1b2cd221ac3a035752a281d4828e6ba72f5cc9ac470a90a819716135b1b9e 0 +/usr/lib64/erlang/man/man3/wxGraphicsContext.3.gz 92109ef92c79b2b95457e3a5262d85c16a468950a6b0ebee92fd6472876cf560 0 +/usr/lib64/erlang/man/man3/wxGraphicsFont.3.gz cb9d5cc29421858aec886a2b544744cdb2a9e703fd62e420fd9399f9159b7c29 0 +/usr/lib64/erlang/man/man3/wxGraphicsGradientStops.3.gz 5bbb7164de9b17ebde39798f9f93b749c8dfba6eb7f04593410f457ca7b68c2c 0 +/usr/lib64/erlang/man/man3/wxGraphicsMatrix.3.gz 75b61b7debd48bc7227fbdb173392dbaefb679aa2f0e77da98c9c1ddb2ebd6e6 0 +/usr/lib64/erlang/man/man3/wxGraphicsObject.3.gz 96e1a94bb7aa2fc9cc07ee19de801381e4ffef5be87a8757eed97bc6af58902a 0 +/usr/lib64/erlang/man/man3/wxGraphicsPath.3.gz 5608c29422c3fc08c761520e7e4e01d3973dc9b1391eacc4d8786bf56954e738 0 +/usr/lib64/erlang/man/man3/wxGraphicsPen.3.gz 4d4b4da3bc43a5166f6b55bf13bb1243c51455e127a311968e809c257c7ee66f 0 +/usr/lib64/erlang/man/man3/wxGraphicsRenderer.3.gz 2b95938ff413d157a7824b5e887de26ee1004ecbf2eb41d0d4834a795ab7776c 0 +/usr/lib64/erlang/man/man3/wxGrid.3.gz 58f1d90a75e564106fcccd1563752689ff93f531f4c56d03def90cada5c36176 0 +/usr/lib64/erlang/man/man3/wxGridBagSizer.3.gz eb564b107bbc835ab0b8d1f9608047089309987efd38180e2f38789823c91b38 0 +/usr/lib64/erlang/man/man3/wxGridCellAttr.3.gz 32be0edf40489020bab1832c9bb5df229cd93320afdd47269654880cfb96415b 0 +/usr/lib64/erlang/man/man3/wxGridCellBoolEditor.3.gz b26b24a53436069dafff20118172b7590ac4720325f672d5907d246f3a6eb599 0 +/usr/lib64/erlang/man/man3/wxGridCellBoolRenderer.3.gz c0d2edc35e80d9218e3aba84317a5c8a652e4e2885ccc81070c2eec80ef5e2d2 0 +/usr/lib64/erlang/man/man3/wxGridCellChoiceEditor.3.gz 258e36fea2325672c633ef73f40bb2650bce2c31b6c35d2c4adc192cf29b7c05 0 +/usr/lib64/erlang/man/man3/wxGridCellEditor.3.gz c57f0573e9667ceb1b0627fed35e92f392f12b6d58125d6bc1830fc2dc787671 0 +/usr/lib64/erlang/man/man3/wxGridCellFloatEditor.3.gz 0195adc9697aaed32533072f6ff119e9e9e8708b6b0eccc7ebef6948df34af40 0 +/usr/lib64/erlang/man/man3/wxGridCellFloatRenderer.3.gz e1e58dbb8d9c631188b6db81c10fcaed117d300375d1244734731923d324419e 0 +/usr/lib64/erlang/man/man3/wxGridCellNumberEditor.3.gz 4badfa82206b69a74ea6ab76d23beceafde82656cb7cc879a446b77c4bfc6c6c 0 +/usr/lib64/erlang/man/man3/wxGridCellNumberRenderer.3.gz a8e8718b7dee36dab13fb57b6ab976953756b74964cb28276a6084d6ffa78fc1 0 +/usr/lib64/erlang/man/man3/wxGridCellRenderer.3.gz df6bdb88f0f04e6d9eb8182ea42b57df7c604b53eb60cb7a0eeb4ef4fc99d497 0 +/usr/lib64/erlang/man/man3/wxGridCellStringRenderer.3.gz d37dd23e26ac7436465713fa024ad431a2c32505581b448b76d02b8f799f9744 0 +/usr/lib64/erlang/man/man3/wxGridCellTextEditor.3.gz 5c33f602a69833590cfe578369823a5555bcc101a0f3ad96cf081d8a61ed6be2 0 +/usr/lib64/erlang/man/man3/wxGridEvent.3.gz 7ef5e8fcc3657cff4e0606a053b1ffbe91fb0a21a1e15c81605c079fad9b5750 0 +/usr/lib64/erlang/man/man3/wxGridSizer.3.gz ceb1eff986c8cef04ff2a656748269dbaca37d1ef3c5cc9c6a4f380cefa004bf 0 +/usr/lib64/erlang/man/man3/wxHelpEvent.3.gz 74689fa71e9e514c08eb153acafdff593357bc15cc6ef53a6600b8d72cac9bf2 0 +/usr/lib64/erlang/man/man3/wxHtmlEasyPrinting.3.gz a5ced4a2511b9ef3834f4e59fcbc4a49222bed3a0f3cbb2f76aa984f376fa511 0 +/usr/lib64/erlang/man/man3/wxHtmlLinkEvent.3.gz 833856ec57eb6e6d7d0e966fa5e77785cb2c4f6cc5c08f6b6ef45501b5a8719a 0 +/usr/lib64/erlang/man/man3/wxHtmlWindow.3.gz 50a5e25f71e27ccaddd7faea4d50fd74d78f2bda752a2e0a28367eecde93bcd5 0 +/usr/lib64/erlang/man/man3/wxIcon.3.gz 4a4f102636b22caca1a91a08cae77c62fbf4f43059bd124a6c1f6b640a8d2efe 0 +/usr/lib64/erlang/man/man3/wxIconBundle.3.gz 98a7cd297229ccf0578a015f6ccec7acfd553d01167a2cb21ed809c5b49d874e 0 +/usr/lib64/erlang/man/man3/wxIconizeEvent.3.gz 4a84897df9037c3f3d5144ad8d3ab6826d2cb3c6e413ad3c9a6d7e8e99d11e14 0 +/usr/lib64/erlang/man/man3/wxIdleEvent.3.gz db983337a8046ec632e703c4884b8d07c3444935cfac04a44a37c026bc41f273 0 +/usr/lib64/erlang/man/man3/wxImage.3.gz 9e129d3e90c71daf2da395fd2ea91b910cf0d4e22f626414ea10ff83dbe7de8f 0 +/usr/lib64/erlang/man/man3/wxImageList.3.gz dd08cd0e652ef66852600d7b6b7cd1c2bda0752615a7cf0d6ff27694e6f1ce30 0 +/usr/lib64/erlang/man/man3/wxInitDialogEvent.3.gz 708660135c1b5e7b3490e995e9963f6107502dc104d51a35b2500fdb14ba1703 0 +/usr/lib64/erlang/man/man3/wxJoystickEvent.3.gz 0e7ec79665d40f9a55a498d0dd8aecf2362cc547c882b11478e9462a26451433 0 +/usr/lib64/erlang/man/man3/wxKeyEvent.3.gz a3c5223986d118763a63f7c072f9b124da40ed6a6a74f1c8460c640a7f48a7e7 0 +/usr/lib64/erlang/man/man3/wxLayoutAlgorithm.3.gz a29ac16fd98e4392f0f47949d14b0764a807789324313739af36c2f7b3853895 0 +/usr/lib64/erlang/man/man3/wxListBox.3.gz 9fa9554c0be75363b951180a74f63b076d037ba022271214916581b785186314 0 +/usr/lib64/erlang/man/man3/wxListCtrl.3.gz 5e9d51312a661b4b587ab02b056b010d1ef029b5c23bbb9920e0c10f154a033e 0 +/usr/lib64/erlang/man/man3/wxListEvent.3.gz 38579925604ffcd8bcdf6f2e2687b52afee31ed99e300bfb941179c255d0d959 0 +/usr/lib64/erlang/man/man3/wxListItem.3.gz 7614ec70a70fbc1e809fa4624d311b63d79db300985ed6c67c96832c587a0061 0 +/usr/lib64/erlang/man/man3/wxListItemAttr.3.gz 7b7f1b56986a6a5bb46ea275cd50bc8f458af749b93cc769d4fc1ec0f29b8cc6 0 +/usr/lib64/erlang/man/man3/wxListView.3.gz ddc0ac8e614e2a5bd11fe6c5f574845ffcbeec4ff9f9de69cbd51e40ee67959b 0 +/usr/lib64/erlang/man/man3/wxListbook.3.gz f94f6377300a9aea55a0d720d02f83f1f1ba1bc936ab3378ebb32e434b7c7fd8 0 +/usr/lib64/erlang/man/man3/wxLocale.3.gz 2f60c8f04539ce03ae11d5dec7f15359e10ab5495da9d904dc871919b68d8bae 0 +/usr/lib64/erlang/man/man3/wxLogNull.3.gz c347fa179cba35507cbde04749db58d875dbda9782f1f9f5c5e8d53d875f3d58 0 +/usr/lib64/erlang/man/man3/wxMDIChildFrame.3.gz 766a0aa4c405ada3bbf8dc311fb16f64a8feab5c5ee9ddae95193182e0b8244f 0 +/usr/lib64/erlang/man/man3/wxMDIClientWindow.3.gz 69bdf786881468b47d1367f03f757d828a518acabeef1230b0a6feecf69d2d57 0 +/usr/lib64/erlang/man/man3/wxMDIParentFrame.3.gz fb48150934af403cff8d1ca7f3915b3272a4044b03665541b9e20ff589b842cd 0 +/usr/lib64/erlang/man/man3/wxMask.3.gz a1946c4c3ff6971b9986fbd6ab522691a3f8f5abe8cb335b1b5965edd46f67cc 0 +/usr/lib64/erlang/man/man3/wxMaximizeEvent.3.gz 045f4747e8ba108d38dc35ffb922be319d9ccf54d85d9a1a3e1cf63c729d3a79 0 +/usr/lib64/erlang/man/man3/wxMemoryDC.3.gz 4be38edc6a91b9ed2084102dd7e18ed27c57e577567c9b4e2097213d65b07dea 0 +/usr/lib64/erlang/man/man3/wxMenu.3.gz 2b1424e5a6466c014e67d5000b01eb78c18cf3d1e737a273e324416b1f1f7137 0 +/usr/lib64/erlang/man/man3/wxMenuBar.3.gz bdb41ddf7b6b99d58ab586816857b4fd90723123a4b8babc567be722cc2df62b 0 +/usr/lib64/erlang/man/man3/wxMenuEvent.3.gz 3be2f9c6824db0182d2b34887bb5ebb7556528d31d09768a5c4638af07a12b70 0 +/usr/lib64/erlang/man/man3/wxMenuItem.3.gz 250188c5ba89a9fd24d7ea69c8c670b522743454af4a0b45b546c802f6f074a7 0 +/usr/lib64/erlang/man/man3/wxMessageDialog.3.gz 4993f9cf89978fb60fc5054b43033ef12aabc7240ce80edc9fe5207e068d7f1c 0 +/usr/lib64/erlang/man/man3/wxMiniFrame.3.gz 478c310b3aa2882f722c91c2ac5396cf760e4d1c5a0b8dcade1fa6a8fbb9927c 0 +/usr/lib64/erlang/man/man3/wxMirrorDC.3.gz ba19f99e1bf51b96a059abe784ea48df04c675592cb2392305dc650b1ddecb12 0 +/usr/lib64/erlang/man/man3/wxMouseCaptureChangedEvent.3.gz 484c6567e58fd137d040fad9f3bd65572bb99d4919ab70b748646a2c34a6b38c 0 +/usr/lib64/erlang/man/man3/wxMouseCaptureLostEvent.3.gz 2966d6e2035cbbc49f2ae6a55781dceb4946527d7cb7bffccdef2e89cdc64e2b 0 +/usr/lib64/erlang/man/man3/wxMouseEvent.3.gz 3333d73ef8c7b031eda4f72f867524c8ede1e2325cbcecca229757c919a865b5 0 +/usr/lib64/erlang/man/man3/wxMoveEvent.3.gz 0bfb07975002d1c7af42e7f86cc4905aeb5ca5752f51ae25c7afbcbfbba8eca4 0 +/usr/lib64/erlang/man/man3/wxMultiChoiceDialog.3.gz 3e230bfe5fd62b1e2cfc49bc83f2c3aa38133203d0cc6ea81297cb662aca84ca 0 +/usr/lib64/erlang/man/man3/wxNavigationKeyEvent.3.gz 9c90c33f2fd8b68c21471ad6d3848a3ae270b3ff7a067bc9c4d1bfca29fae9b3 0 +/usr/lib64/erlang/man/man3/wxNotebook.3.gz 83d9fced3fc6f3c4f46bdd3881d84837b2f1e2407a44dd3743bbb32a06628ad0 0 +/usr/lib64/erlang/man/man3/wxNotificationMessage.3.gz e695538a9e1afcceaf534d6d73600113ca75d95dc82627280e177a9a54703610 0 +/usr/lib64/erlang/man/man3/wxNotifyEvent.3.gz 740e3c5330264047585d18b8c4c0553db6b962cdbaaa571dfc170c04e856156a 0 +/usr/lib64/erlang/man/man3/wxOverlay.3.gz e9c1f060ed3f25b92342a4cc331595c489ba7bc97efdb4342fa5d91dace5a4a4 0 +/usr/lib64/erlang/man/man3/wxPageSetupDialog.3.gz ce8c793ccd61c26d7ed278afa9a5ea7eb2e77684982099fd244068610bf3975c 0 +/usr/lib64/erlang/man/man3/wxPageSetupDialogData.3.gz dd7b1f20b21f80b0d014aaaa9932d5cafe44939b3a04b95f4265f4f6b2df8338 0 +/usr/lib64/erlang/man/man3/wxPaintDC.3.gz 30ac437315612f731509e3f76d366b08c4c54fb168728b1ed6884534b89c0a3d 0 +/usr/lib64/erlang/man/man3/wxPaintEvent.3.gz 44a28c272816b506d4301999940e34f4d27913788c4b28508d3327a420b1022f 0 +/usr/lib64/erlang/man/man3/wxPalette.3.gz b6a3739ee380b20f2d764f91133dd242bf9773b7cb6ecc45f26484c81d097199 0 +/usr/lib64/erlang/man/man3/wxPaletteChangedEvent.3.gz 188739278fe5af32d6c418cddd0efe8a27b65e01844af24163dda82ea49969a3 0 +/usr/lib64/erlang/man/man3/wxPanel.3.gz 810d42ac49dc9c1c713cca97971afac4357238b99a43923988fa800be7be0c50 0 +/usr/lib64/erlang/man/man3/wxPasswordEntryDialog.3.gz 8cb9f473badcc41bf6a39981aa8524e07cfb87d0689211a2b9fd0f93cd305e59 0 +/usr/lib64/erlang/man/man3/wxPen.3.gz d9a36c217862d891d7a0b3e3f159fee00f380c54a173ffac584bc3811bae7b22 0 +/usr/lib64/erlang/man/man3/wxPickerBase.3.gz 83a98b342152ce1702a60784a3581eea4d5dd19a6f3270065aed6a4a4b173473 0 +/usr/lib64/erlang/man/man3/wxPopupTransientWindow.3.gz 404e6d4e11f985619c0286ce3153a0b795f921afe0b1b438ba15e9a7e55872ab 0 +/usr/lib64/erlang/man/man3/wxPopupWindow.3.gz 887c4af005391cff549d3f8eb63904f87614af535a7765de2eda3235731faddd 0 +/usr/lib64/erlang/man/man3/wxPostScriptDC.3.gz 9bd6fc5e801f43f923192143532835f6f48f6fac957f20bcf6020e3a563c4b68 0 +/usr/lib64/erlang/man/man3/wxPreviewCanvas.3.gz 0186e62283b56fce05231bff18c2ae9294418cc329b3269ae4795d525087f3e2 0 +/usr/lib64/erlang/man/man3/wxPreviewControlBar.3.gz e7613a1020c84463a2c1d1b338b4171a1f9e028a4c0225bd17ead5f0d884502d 0 +/usr/lib64/erlang/man/man3/wxPreviewFrame.3.gz 45f22b2670b33e110b8cfa43d483002c3b605cdcd1659239ad05c97b8c0f1358 0 +/usr/lib64/erlang/man/man3/wxPrintData.3.gz 2b6d6c78f4c09060d41440999916cebba12a63022a8112b28f5111661174b120 0 +/usr/lib64/erlang/man/man3/wxPrintDialog.3.gz d713f42d3757e1877a0099ad0b305f6567e66b93d566cea403f5db57c479cf50 0 +/usr/lib64/erlang/man/man3/wxPrintDialogData.3.gz b122880c5973ad25327578f58b1726cdac514f82917ebc258d923c188ed746f3 0 +/usr/lib64/erlang/man/man3/wxPrintPreview.3.gz 302b6bfbebb762a2365e4d8f1101c0fbae4e75fe25116c7be376cebf0147ab32 0 +/usr/lib64/erlang/man/man3/wxPrinter.3.gz 52bb873eb73fb15a8fc7164f1e3c6537f2fa1354c456847a4fce86cef57998eb 0 +/usr/lib64/erlang/man/man3/wxPrintout.3.gz d8a73d87e82fe5b1cffa9eed28bc196502e47d62554f3f691f58b67de2532f5b 0 +/usr/lib64/erlang/man/man3/wxProgressDialog.3.gz b0af7481e1a531423248c71152a2dd2ca2573c8aa122d43515d48dc2e3c6cb3d 0 +/usr/lib64/erlang/man/man3/wxQueryNewPaletteEvent.3.gz c073cf5e481e9c3ba4e02693b25146958d6f1f418c060a7701eaa423835d4d9e 0 +/usr/lib64/erlang/man/man3/wxRadioBox.3.gz 016849bc4acf40a1713e4a62262692b4d56a73a46ebb13ed00910cc42684f544 0 +/usr/lib64/erlang/man/man3/wxRadioButton.3.gz 868afd9f6cea0168347734a8aa5224b61996e5bf2927646d7a4db27820991b05 0 +/usr/lib64/erlang/man/man3/wxRegion.3.gz 11019e4a589f8612de77dff45e7a3be2b64beefe83988aab36fb584396e552d0 0 +/usr/lib64/erlang/man/man3/wxSashEvent.3.gz 2655160707f6bfc0099ec873f8660c056cd648b6800c82f46daf1e8a37affd31 0 +/usr/lib64/erlang/man/man3/wxSashLayoutWindow.3.gz 03ef3f025981ff377f8b846959c3b2f71f56926685b56d2c25729d095064d052 0 +/usr/lib64/erlang/man/man3/wxSashWindow.3.gz 0e437c39a5d0c2e9be1201138651d4ac2fd3663606d20db41d5bd3591b44fb3f 0 +/usr/lib64/erlang/man/man3/wxScreenDC.3.gz 6dbec7737bd0dbafd0afe413ac7de3fbbc4c1c19c637047a2b303ede2bb7cbcf 0 +/usr/lib64/erlang/man/man3/wxScrollBar.3.gz 6fb86733dc079e81032c10504c4203bfe2cfae432646395330a7280d7e0a451a 0 +/usr/lib64/erlang/man/man3/wxScrollEvent.3.gz 9c17d4f31f74709cbe72fb7990db87b5683bd9c5bb0176e82d77ede6faa4c340 0 +/usr/lib64/erlang/man/man3/wxScrollWinEvent.3.gz f80c540556e1299c38db4a0dd7bf607a8f9ece270b9fc068f5729ea3bc0fb75a 0 +/usr/lib64/erlang/man/man3/wxScrolledWindow.3.gz 675a00629a26b9b8dd5befa70937a78c24c817030191dcf874f6d5a5635b4684 0 +/usr/lib64/erlang/man/man3/wxSetCursorEvent.3.gz 9ae203d9e9c55199b3039fb0ed4b6b604dfff82f7f5178b5c19cd119827b806c 0 +/usr/lib64/erlang/man/man3/wxShowEvent.3.gz f42d504a6f34ee495e01ae2cd5473a4c0d805a302818f1d582dceca333f3a7c2 0 +/usr/lib64/erlang/man/man3/wxSingleChoiceDialog.3.gz bd05449015f49d6bce2311238e14e4c338200c556894862bb0ca92551f145772 0 +/usr/lib64/erlang/man/man3/wxSizeEvent.3.gz 0c0bd5aef2fe3cb4d7a5eeb6decd935cca64651f94dac0e785dc149b099ee409 0 +/usr/lib64/erlang/man/man3/wxSizer.3.gz 9739dbf4cb10eaa88ba3b92f7064676df2c5bcb13169b06ab8544f4a144af48c 0 +/usr/lib64/erlang/man/man3/wxSizerFlags.3.gz 0ab5ae0ab0fa902f4347a5adf86bf0bd49fd744b96b21b453df3702bb252e915 0 +/usr/lib64/erlang/man/man3/wxSizerItem.3.gz 1b2aee90a32668d4bfc701458a590b2975e87f6f6a44a08324d17cb3e124d658 0 +/usr/lib64/erlang/man/man3/wxSlider.3.gz 047bd0f0e2337dd1331df044902854ea0e1eea92ae2af00d0363c3900926d48f 0 +/usr/lib64/erlang/man/man3/wxSpinButton.3.gz 70ae1f6d383fe7ad16987dc91669ec7f1f9f3de200133a5b7e6778231010935e 0 +/usr/lib64/erlang/man/man3/wxSpinCtrl.3.gz 20de76830d1355d75efbf8c82f1743c8aa030313b505699b9df48d2331aa7bd1 0 +/usr/lib64/erlang/man/man3/wxSpinEvent.3.gz a535d3f91d9aeeb3f2aedc8f78885377e252dfdf6d05ade0d82ae66c2d5c5f87 0 +/usr/lib64/erlang/man/man3/wxSplashScreen.3.gz 6869684b26afd8012a0361bf91a7ec0d2c92f0afe3878f7ebf0b19ca5ca9dbef 0 +/usr/lib64/erlang/man/man3/wxSplitterEvent.3.gz 7cdc2fdf68042c4064d2411a00c3309f0160f97655ca2f306009b7bac445e7a3 0 +/usr/lib64/erlang/man/man3/wxSplitterWindow.3.gz 6e1b9c7878707cd97af60f0848ebaf5718944453c41859649932ef96c999b6fa 0 +/usr/lib64/erlang/man/man3/wxStaticBitmap.3.gz cf69692187a4e19510a38567acee6ad4e2f6352ad9b51c9835cc17b3d3888813 0 +/usr/lib64/erlang/man/man3/wxStaticBox.3.gz f0554623ae084181cf3f0aa0decb80c5014e4f495517b7c72aee82fc0a44afc8 0 +/usr/lib64/erlang/man/man3/wxStaticBoxSizer.3.gz 9639cd6b1646905ef9be8fc8693c7d1b956f188ffce1ad12e718fc4c52782bde 0 +/usr/lib64/erlang/man/man3/wxStaticLine.3.gz f5f6a978a67055427ca6ebf8caef5756bb5318d4751e49d1e5bf4497fc331548 0 +/usr/lib64/erlang/man/man3/wxStaticText.3.gz 9ae1a975af777cf4ff6aa2f9be62301434c0ac364397a1ddf8af9ec3786fa512 0 +/usr/lib64/erlang/man/man3/wxStatusBar.3.gz b3376aac314ffda2075e93a9601462816f15834c75062803119c4b27daf9ebdd 0 +/usr/lib64/erlang/man/man3/wxStdDialogButtonSizer.3.gz a69a45914378ff06fd399ae6a6ee9748f12798f88ab91495e47e0d792deb2f38 0 +/usr/lib64/erlang/man/man3/wxStyledTextCtrl.3.gz b45dc339da67b1cdf77fce52c60b774ddd09758f7834b60134e807b7ed7d5466 0 +/usr/lib64/erlang/man/man3/wxStyledTextEvent.3.gz 7ecdaf5454c5f2042f324fa5a900bca2d5cb23d2958b2fe739b8ed5e1b2f61de 0 +/usr/lib64/erlang/man/man3/wxSysColourChangedEvent.3.gz 8806c8f915abfa633522beca5fb130f613a444c09d0af53704aba9b8fe8e202e 0 +/usr/lib64/erlang/man/man3/wxSystemOptions.3.gz aeadfe00502f4478ca76e550892aea7507c493d3c1a7e601d398c9bb7da3bc9a 0 +/usr/lib64/erlang/man/man3/wxSystemSettings.3.gz 2ca6b9dab28c289279424556072e18cc448f98b41541affbfa863f1961115127 0 +/usr/lib64/erlang/man/man3/wxTaskBarIcon.3.gz 63b83e5635771b20b0738057a57ef7dadad6db7b1735a886ce0a1d1c28e79c70 0 +/usr/lib64/erlang/man/man3/wxTaskBarIconEvent.3.gz 8ecd1d7ef7b6c7b8ebdcd28d83d5a200ad712d25f3cf397eae1baf49d6c58fa0 0 +/usr/lib64/erlang/man/man3/wxTextAttr.3.gz 4e2d32be68f8106ed09b97d08a7f85e0b95fc68056638bb8657124c4c2d1ee4e 0 +/usr/lib64/erlang/man/man3/wxTextCtrl.3.gz b3604d100d3079ae206695848d9eca4e91da6cc33990209a748f406664dfca12 0 +/usr/lib64/erlang/man/man3/wxTextDataObject.3.gz 260a717a0afb57414be95c80330c69b395c3bf3f864248ba578eb0426903a16a 0 +/usr/lib64/erlang/man/man3/wxTextEntryDialog.3.gz d688d0bbfa30efdca03aaede0607626fda9cb0d55be376c6e51cd443d2adb8ac 0 +/usr/lib64/erlang/man/man3/wxToggleButton.3.gz bdf68f5b3ec8fab3c893bf6db2e9d30e4d632c6e984283100abece2336314b5b 0 +/usr/lib64/erlang/man/man3/wxToolBar.3.gz 5d8de3a4a778c1a87380874f457f6c57006355570365f62ed7755306e9209544 0 +/usr/lib64/erlang/man/man3/wxToolTip.3.gz 73d9ee9690956f35134ab931bd4db3df27b697af1346e5f295100db57fa4e5fe 0 +/usr/lib64/erlang/man/man3/wxToolbook.3.gz b61dd9457b9f4d01068800158816eb94e1bff52b692fdf79b86da32269968baa 0 +/usr/lib64/erlang/man/man3/wxTopLevelWindow.3.gz 5f3aff569a96cf2b7b69719624d140801b0ef3e06dd43582a597fffa7508e28a 0 +/usr/lib64/erlang/man/man3/wxTreeCtrl.3.gz ab161a9a1635160a997ba1c9355db6b1d41023430b37206ba5e1ef5a9105363a 0 +/usr/lib64/erlang/man/man3/wxTreeEvent.3.gz e3ceea4826426562dd6ac0a091967971fceba69ee7c5e34e75ea46b3bc1dfcfa 0 +/usr/lib64/erlang/man/man3/wxTreebook.3.gz 24d68c8a80a129043bf1dcf957f941d145b2d0cd5f448257e2842f3f244eab6c 0 +/usr/lib64/erlang/man/man3/wxUpdateUIEvent.3.gz 6cafaa472807402b39a1cccc509750194433b6ad9152eb8df273a38df55ff2cf 0 +/usr/lib64/erlang/man/man3/wxWebView.3.gz 6fa34f2e45049d5ff2eaf0a9c7620b68fa8b54f19e5656adee324224611f557c 0 +/usr/lib64/erlang/man/man3/wxWebViewEvent.3.gz e65ade654e34816ec0c5189c73a7b2bf15b4d071743ae1c08072fe5841c8af07 0 +/usr/lib64/erlang/man/man3/wxWindow.3.gz 20ceb79aa1680df634e69885aa5b7b3fe4e5128a0a7f8a71f259c0645065385a 0 +/usr/lib64/erlang/man/man3/wxWindowCreateEvent.3.gz 9bccb1b1db6b49446ba0ddb0014666127cbd616efe1d723f70f9351e4768c3b4 0 +/usr/lib64/erlang/man/man3/wxWindowDC.3.gz 84b5c8a4074845aecd99c7bc9be0d5efc1e7ac1599088864944d653dce2c4d35 0 +/usr/lib64/erlang/man/man3/wxWindowDestroyEvent.3.gz b5484cbfa9ff9af815d6ae75bcaa378f2843a70d33d6d98c2c1c7bddb9923f53 0 +/usr/lib64/erlang/man/man3/wxXmlResource.3.gz 6e3d61725bc0fd67a5edfda2328812237c328f5df5b7db925bb97dd0912844a8 0 +/usr/lib64/erlang/man/man3/wx_misc.3.gz 9fc2e4c9fd842ede47e67ea0a25a5f75c080677bccbf286134fbb51832da60d9 0 +/usr/lib64/erlang/man/man3/wx_object.3.gz 17d7facb7511421a20def72402d7bf41c0e27d2bf5ecb8239e7be1ae99738c3b 0 +/usr/lib64/erlang/man/man3/xmerl.3.gz f26a67cd821e82bd930e76602d970de3d697c41fbb22acbec96c0ac5d889184a 0 +/usr/lib64/erlang/man/man3/xmerl_eventp.3.gz 5e678b79e4f04bec937685eadef2a7be8fbe0ba777d4d427c7b211f7a5443002 0 +/usr/lib64/erlang/man/man3/xmerl_sax_parser.3.gz fc82695895f637c8de5b84ff2131235200f5c9bdbb7b61ceb7fac0e811a33f22 0 +/usr/lib64/erlang/man/man3/xmerl_scan.3.gz 22c7fc665695ed355668f9804d46b44011ff7c6beddef9047219ccbe557b5837 0 +/usr/lib64/erlang/man/man3/xmerl_xpath.3.gz 2949730ab1c331f376e5d6a4a195342401305e3b5afd35f018d2c249a42b0025 0 +/usr/lib64/erlang/man/man3/xmerl_xs.3.gz 66a8b1df7e68a80b96745092a8469c31ab01cb3b23c74ffe210ebe6a372c929f 0 +/usr/lib64/erlang/man/man3/xmerl_xsd.3.gz c104ace58eb08b25f490b041a6e79213ba0300ba8a6af97e6a19b47193347530 0 +/usr/lib64/erlang/man/man3/xref.3.gz 08f3ae1a946e418ed4f14c8c945294b03872f422c24c541cafe9b3a54eb72f82 0 +/usr/lib64/erlang/man/man3/yecc.3.gz 96387960b1d71c7fbd1541047f33d7b053f23ecc1f3c01feac2a0b1531e59c7d 0 +/usr/lib64/erlang/man/man3/zip.3.gz 3f34f0e77d9e44481719765a9de1d59b3f022df50c6d3ef4fc1d72d3468bf660 0 +/usr/lib64/erlang/man/man3/zlib.3.gz 9e45c8988ab315e0ab11a26822a592350f32f123925e29f51c7cd6a4a8712f54 0 +/usr/lib64/erlang/man/man3/zstd.3.gz 26ab507c51d4e4be3505f24627d7182f5251e822b844791175f2e1eddca3cbf1 0 @@ -4182,8 +4182,8 @@ -/usr/lib64/erlang/man/man4/app.4.gz 1dbd3a654282192a141445188182f68d75b181214e56c733109c8bca9442663d 0 -/usr/lib64/erlang/man/man4/appup.4.gz e09fbe870f6d3ffe1392a1044fba149eae0fcc120d296ba73ef3bd7a44d3d456 0 -/usr/lib64/erlang/man/man4/config.4.gz fc0f3c7704a6315680eb6a1f085898ac98f41cd989d0d129d77b9a960fd15741 0 -/usr/lib64/erlang/man/man4/diameter_dict.4.gz fea31e960641106d471a79da61ecbe7831b850cf9dbe40113a7384f5bbf9408e 0 -/usr/lib64/erlang/man/man4/erlang.el.4.gz 9c40ad2b6351abf2b045470a7fa636a7cb02140adcdbbde50c4b048c368bcf76 0 -/usr/lib64/erlang/man/man4/rel.4.gz c923461df9ad7089f689ecedd23793f4e6e6b658cfbbdbbe04c2fe10c827caee 0 -/usr/lib64/erlang/man/man4/relup.4.gz 05c73085e68c785ee2ab74abf4abafb6b7878f2c695d55c2fc076f9f42bfc080 0 -/usr/lib64/erlang/man/man4/script.4.gz 0c6de816425dda8f82f5167262c56b548383b8dd4736e0f7230cfb8938d0c2cc 0 +/usr/lib64/erlang/man/man4/app.4.gz 3c15e463363641f8240a2cdd6be694b411c049fff632bc1b43f3b2eb2d8f870e 0 +/usr/lib64/erlang/man/man4/appup.4.gz c3a49be0e601aa13b6f5c5b4c8864831b80964de15a5f25fcdb468db448ea8d5 0 +/usr/lib64/erlang/man/man4/config.4.gz 6012d92cee77ad30cc86c4011c3f97a9bad2ce3381b9d704fa379f5f919a69fe 0 +/usr/lib64/erlang/man/man4/diameter_dict.4.gz bcec9ab26b3d1ea4acf48d6125bf4b857cf739b8c485e6b897639a4498acf630 0 +/usr/lib64/erlang/man/man4/erlang.el.4.gz 9caf405e613550d741180b83ee06d6976d00c1986b20db8c7e1207621be16f38 0 +/usr/lib64/erlang/man/man4/rel.4.gz 584645c536550b195e300dd1c5b7329bec6b91c97403a3d8c313147581df40f8 0 +/usr/lib64/erlang/man/man4/relup.4.gz 0e31a03f4325bdb9a2ea7ddf04eeab03b0bd31b67d28c1bf83c893d1df03dd71 0 +/usr/lib64/erlang/man/man4/script.4.gz 19112800c403b349d3775ee11720eb5a0dcb9cd5c7451768c8495c6f187e53ee 0 @@ -4191,12 +4191,12 @@ -/usr/lib64/erlang/man/man6/common_test.6.gz 4f81f5def888ffec77d790dfefdc9dedee37806a3ae4b1db0e162c9cdb6304f4 0 -/usr/lib64/erlang/man/man6/crypto.6.gz 51c04251457cb5634472657b051ee91b6a3fe5d1fea2365c2ffebeacd5c66cd7 0 -/usr/lib64/erlang/man/man6/kernel.6.gz 02ab4bd7c3c28797a75cff59d4c4aa0e36ef20f09936c59981bb2b21685e5e69 0 -/usr/lib64/erlang/man/man6/observer.6.gz a8af2f64066b20b6bdc496cf3ff53eaa1cf785e75dad09d8d5f3c3808cd4f18f 0 -/usr/lib64/erlang/man/man6/os_mon.6.gz 47caa783896526da7ffc90bf3612a35d118a0639de47adb098d077948fdac02a 0 -/usr/lib64/erlang/man/man6/public_key.6.gz 418c4a8904c437fc73c86900efa65c1cde2fb34e89dc80d16bc3f9920516909f 0 -/usr/lib64/erlang/man/man6/runtime_tools.6.gz 6c96ecbd1ed170a679696fa834f7e98965bb6af88f6da99c5756fd9e27830752 0 -/usr/lib64/erlang/man/man6/sasl.6.gz f8041f7c9926be8cb79d83c6793fac55abfc256c9eb98b849377c3acd01f3070 0 -/usr/lib64/erlang/man/man6/snmp.6.gz 64f73259d83cda38ada6edcffad9213f970f059486c2d56d7dde80aad2fa54c6 0 -/usr/lib64/erlang/man/man6/ssh.6.gz 1588f75090adf76d1d53b165a1665aabce0b644a7f8cf0309429bd3ef77a781a 0 -/usr/lib64/erlang/man/man6/ssl.6.gz 8fe4a40f3e213f28eaccd1e1cd5c232d3ead7732a12d1cf56a42aa85b2ac41ec 0 -/usr/lib64/erlang/man/man6/stdlib.6.gz c3767bdd9dd5881e378ff60604e8a821d58dc727f545fb81cf9f9fa480b69f8c 0 +/usr/lib64/erlang/man/man6/common_test.6.gz 1262ebf714aad0eff87a8003d5efa036b1089267e3ed9b2e7be393d660a2a298 0 +/usr/lib64/erlang/man/man6/crypto.6.gz b08855628261d84b87db1214378867de34ea8dc86074fc61e31ac816f01288a9 0 +/usr/lib64/erlang/man/man6/kernel.6.gz caf294957883dc08d7f9d6d365814724471ec1b44dd058ac663e5488596cf43e 0 +/usr/lib64/erlang/man/man6/observer.6.gz 1e1cdc1d08b6b478c5ce1c388cd70317145fda1087be2d3673ebfc9632033c30 0 +/usr/lib64/erlang/man/man6/os_mon.6.gz c9e000f18be5d1c3be034024d634858e621ae15edbcde3d6bdee34e6d1f6b36e 0 +/usr/lib64/erlang/man/man6/public_key.6.gz ee5542ef38d032a109ea4d6035c2eef3c539ffe6b13ac7688208952ac0a2e9eb 0 +/usr/lib64/erlang/man/man6/runtime_tools.6.gz 6bf2a11777b97e4c8b14da9b9bac4d195dffb1913808ad19a8d46557a1b0594f 0 +/usr/lib64/erlang/man/man6/sasl.6.gz 5b289055af53de286a3ff0bf1ee7f69270d1ede6cec67733eca12e207dcc4ba4 0 +/usr/lib64/erlang/man/man6/snmp.6.gz 3a4da8df4f5723038c86b75e5832889edea238971da32bed807b7abca58c32ed 0 +/usr/lib64/erlang/man/man6/ssh.6.gz fe7b57ff4acbbaeb9da4bb97981796fd51bdd7b797277f83c9325decd5ee4d2b 0 +/usr/lib64/erlang/man/man6/ssl.6.gz bc40fc8722335a25949d5b666025874b4c5f532ba47594e1624d69e9a55497bf 0 +/usr/lib64/erlang/man/man6/stdlib.6.gz ea86a390ecf50fb0815825ea720c8dd38cbba3f3bf8e0bb188cd6d963429fe92 0 @@ -4204,24 +4204,24 @@ -/usr/lib64/erlang/man/man7/INET-ADDRESS-MIB.7.gz 93179093b64650f58a45069233f13f078cc1d117b7b933504b51f6559a890efb 0 -/usr/lib64/erlang/man/man7/OTP-REG.7.gz 38904e5ae3587af876648fd3f7e1ee09fa13875f8f4526998441a61eb7732332 0 -/usr/lib64/erlang/man/man7/OTP-SNMPEA-MIB.7.gz 61a25f04ea65c068bada161f53bda9a7c66f1f79267ac2e3a73877ced336f9e3 0 -/usr/lib64/erlang/man/man7/OTP-TC.7.gz c5d411ef10f7bede0fc2e08439f1f275b5e80fb7fed0b942c29c763de05b53da 0 -/usr/lib64/erlang/man/man7/RFC-1212.7.gz 937a395da3a223f3d940e9dabbe9fc95bb658141f4b15ce0fedfbdd15f9a9886 0 -/usr/lib64/erlang/man/man7/RFC-1215.7.gz 2b78c39b236b042c28d222c014df7b44c34f25a3183b71ca56cd2f063aed8898 0 -/usr/lib64/erlang/man/man7/RFC1155-SMI.7.gz 528b5a5018511e531c53d49a0d77b2cbf08ca198109bfc50a38bd442ab4aea81 0 -/usr/lib64/erlang/man/man7/RFC1213-MIB.7.gz b72af5cee403ac1e9451b4f9595cd483c4aa14c276fba3d6c18fd7966e54243c 0 -/usr/lib64/erlang/man/man7/SNMP-COMMUNITY-MIB.7.gz 3a287ed574797228b64eed60da47e285f5ad9ab50c3a566ee109a427b2f6d162 0 -/usr/lib64/erlang/man/man7/SNMP-FRAMEWORK-MIB.7.gz d5b9b2c2515ed55177a7427f2245bdcbda1fe5ca1620116a85d748683c48cf96 0 -/usr/lib64/erlang/man/man7/SNMP-MPD-MIB.7.gz 10403914254d8693cf72409a217dc45d1cd172803c9df8f23fe3614d7e23862e 0 -/usr/lib64/erlang/man/man7/SNMP-NOTIFICATION-MIB.7.gz c127507534a12252c4abc047cba3e38596188413c901da8b1f4cf829972f8f5a 0 -/usr/lib64/erlang/man/man7/SNMP-TARGET-MIB.7.gz 70f1d59f047beee6796019cc07911cfe8dce270f14b477c09662fad87df93a52 0 -/usr/lib64/erlang/man/man7/SNMP-USER-BASED-SM-MIB.7.gz 6b7c953112efa56c034ad65c16da28bd447f0ab70774fd07c4fdd15d04842fb0 0 -/usr/lib64/erlang/man/man7/SNMP-USM-AES-MIB.7.gz 6fba3a87aaf925a59ddfcef4f68293eaff1d8d584f44f8df1e3b904a49255612 0 -/usr/lib64/erlang/man/man7/SNMP-USM-HMAC-SHA2-MIB.7.gz 4a4a01546f4fb892758cdcb6cd162c4b77a74269409561b70baa980a77a96018 0 -/usr/lib64/erlang/man/man7/SNMP-VIEW-BASED-ACM-MIB.7.gz 7834cad5a744c12853730b41d1f365584c5f0e974ccb5eb78ec7322a2da5c10d 0 -/usr/lib64/erlang/man/man7/SNMPv2-CONF.7.gz 22ac81411ef575901af394d40aa724108c6ae00172a2e444963f263651a0e063 0 -/usr/lib64/erlang/man/man7/SNMPv2-MIB.7.gz 2b14d3ba51cfaef69292f19041c88dadf281c7a99b6bb51d43c9832bc65bb6ff 0 -/usr/lib64/erlang/man/man7/SNMPv2-SMI.7.gz 1bfa0d4eff4b1bc6600e84814ca806edf2dcb6d5e7fde950e234cf5d3d87b7ea 0 -/usr/lib64/erlang/man/man7/SNMPv2-TC.7.gz 07e04fb522ae692c384371644a7c9a2ec169867abfe99f0b0624510253ed15da 0 -/usr/lib64/erlang/man/man7/SNMPv2-TM.7.gz b405161dc595e3ed443a5c0ed57060b13d262eb9414883ead5d80312b3f7d9c8 0 -/usr/lib64/erlang/man/man7/STANDARD-MIB.7.gz ab0c069e2442d866df4ae8887b89affb645b626a9606dcfa8a8f78a1676ed1b0 0 -/usr/lib64/erlang/man/man7/TRANSPORT-ADDRESS-MIB.7.gz df39c22bdb121e5a44bc25e3b179be15427c6a8d2e9de1140f6f885c61b5fe67 0 +/usr/lib64/erlang/man/man7/INET-ADDRESS-MIB.7.gz a9d7ba5c83cd3f2832c8ec15994bb3bd294255d88f5db6ac8d0bda40e0eda68b 0 +/usr/lib64/erlang/man/man7/OTP-REG.7.gz d6dc66eba2d9024b7759f67a6d0c32b7545c9dce3bdb51531da38d0825879104 0 +/usr/lib64/erlang/man/man7/OTP-SNMPEA-MIB.7.gz 48423ace7a54bcdd25d7b8586e0335b7071069e4b2b864d95533c4fa41246467 0 +/usr/lib64/erlang/man/man7/OTP-TC.7.gz 1af5f21a23a0122005a03f795224c0f2899322a8b3b4704fe5f56e7c61f43ff3 0 +/usr/lib64/erlang/man/man7/RFC-1212.7.gz 1088ce94dd4d9b740f5080c1581ce84e391d31ad5a9deece20b39ebc6e8aab1a 0 +/usr/lib64/erlang/man/man7/RFC-1215.7.gz 4fbe8f3feaf4663449e67a49b2bc9e9096d44edcb6f1018a0daeef0d154fd4a5 0 +/usr/lib64/erlang/man/man7/RFC1155-SMI.7.gz 9e2892acf09f6841c0f481c06ba97b2ceecd559681178e91d5a77756e770ccb6 0 +/usr/lib64/erlang/man/man7/RFC1213-MIB.7.gz cabbcc1d448dd6d5c1f309aac8d46b29ca5ea16e75ef7d2f0d6ccbbf6044ea6a 0 +/usr/lib64/erlang/man/man7/SNMP-COMMUNITY-MIB.7.gz 1ae4a4671a34ab897490d88e376ccb162ad769950636ccffe935d6cb61dccdeb 0 +/usr/lib64/erlang/man/man7/SNMP-FRAMEWORK-MIB.7.gz b5e9d6a93b7f9e20f3aa125d48b083b412754b6699e21909c117e590698dff9c 0 +/usr/lib64/erlang/man/man7/SNMP-MPD-MIB.7.gz 408b067dcbe42dbf2945e0353a5210ae589053d5d3e50fbf41f97b6898d08f6a 0 +/usr/lib64/erlang/man/man7/SNMP-NOTIFICATION-MIB.7.gz 7b5c7a39783b2d3f5953d94fcfeb545bbf9071e764f72e31f8f68ee3be11d70e 0 +/usr/lib64/erlang/man/man7/SNMP-TARGET-MIB.7.gz e741dc57d60c9ecced594a316d71fe2416ba3bc6db39e63b05f0d55a94bc9a22 0 +/usr/lib64/erlang/man/man7/SNMP-USER-BASED-SM-MIB.7.gz 6d52bae32666165d6ab95372d7df10531baa81bae2ae56535ec1ee9c2397db83 0 +/usr/lib64/erlang/man/man7/SNMP-USM-AES-MIB.7.gz 07c43e8d2be10f6f0698bbb78bc5558671e34820e92de7dd689965d5867d19d3 0 +/usr/lib64/erlang/man/man7/SNMP-USM-HMAC-SHA2-MIB.7.gz c55df638ec43ea2391dca4146d1d74b0efe7b6c8816f72d74a0f906fd6057d7f 0 +/usr/lib64/erlang/man/man7/SNMP-VIEW-BASED-ACM-MIB.7.gz 53d32c93d7bc9665978b5c7f45d5e96ee648a634e19dd50716209666af965cda 0 +/usr/lib64/erlang/man/man7/SNMPv2-CONF.7.gz fc53bfee48c86c752987d9436263e7a62ea84af840067d444fb788d1fe71e715 0 +/usr/lib64/erlang/man/man7/SNMPv2-MIB.7.gz 1721b545bdf2f4cb136ac8402d0c2e7c658e66c71b9b20b2f6e9ad14e23d3d41 0 +/usr/lib64/erlang/man/man7/SNMPv2-SMI.7.gz ec32145919e6cb77161e52c8f78281938dad96812f6146aa40aad586529290fa 0 +/usr/lib64/erlang/man/man7/SNMPv2-TC.7.gz 8fe9c51db7ad0ae7e90fa344802ec6f2b26787ea48daf80993610724dc1c3a26 0 +/usr/lib64/erlang/man/man7/SNMPv2-TM.7.gz b3b3fd1cb271d2df96dd963c13897fe0f14b3d92a677884727b0467c0edb3dcc 0 +/usr/lib64/erlang/man/man7/STANDARD-MIB.7.gz 60a55a48ca8fb60245807caf184dcb7c6c0637d7dffbc82206c72e9edf34f052 0 +/usr/lib64/erlang/man/man7/TRANSPORT-ADDRESS-MIB.7.gz c0b64ecaa550af466ea137d29bef680fa5359d959cf2643c7cfce98179bdb13a 0 comparing rpmtags comparing RELEASE comparing PROVIDES comparing scripts comparing filelist comparing file checksum creating rename script RPM file checksum differs. Extracting packages Package content is identical RPMS.2/erlang-doc-28.5.0.4-1.1.x86_64.rpm RPMS/erlang-doc-28.5.0.4-1.1.x86_64.rpm differ: byte 225, line 1 Comparing erlang-doc-28.5.0.4-1.1.x86_64.rpm to erlang-doc-28.5.0.4-1.1.x86_64.rpm comparing the rpm tags of erlang-doc --- old-rpm-tags +++ new-rpm-tags @@ -628 +628 @@ -/usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/dist/search_data-B18D77D5.js 2 (none) 100644 root root 0 4294967295 +/usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/dist/search_data-0F342CA6.js 2 (none) 100644 root root 0 4294967295 @@ -2442,3 +2442,3 @@ -/usr/share/doc/packages/erlang-doc/doc/system/Erlang System Documentation.epub 5441d0b1e60d459c2a1503d6e2946de8de147524606f67b56c0b9582f3f098bf 2 -/usr/share/doc/packages/erlang-doc/doc/system/applications.html 92a4ab09ecadcb9006fe28a3c7028b74f2086345254517b6f8e75aaa2908b3df 2 -/usr/share/doc/packages/erlang-doc/doc/system/appup_cookbook.html d21094527ad4ecb01054bfbe271582c407b7a8ac2970e95e9735303116085b6e 2 +/usr/share/doc/packages/erlang-doc/doc/system/Erlang System Documentation.epub 369e7a1afaf90aa44e3d57c90f4e8d69e3455a84a1d838a0aae770aee34e6866 2 +/usr/share/doc/packages/erlang-doc/doc/system/applications.html cc7bc4801d4d2066cd1df67620f11d4641dc2f0dd8d91b44ec2b6e8942e53c03 2 +/usr/share/doc/packages/erlang-doc/doc/system/appup_cookbook.html 09c0fa8dad1b8157084797dadee4bb5e213b00800b05d01f817bfe157fc0bcbf 2 @@ -2455,5 +2455,5 @@ -/usr/share/doc/packages/erlang-doc/doc/system/benchmarking.html 4ef91e5a7e29b462bfb13b16459031c359b33e03c921fa0b12d8bb1265d382f3 2 -/usr/share/doc/packages/erlang-doc/doc/system/binaryhandling.html 908b1843c29333f4e09cc25512b44f0fafb5857ae68748bc7c97ea315f0f82de 2 -/usr/share/doc/packages/erlang-doc/doc/system/bit_syntax.html b66adb36f4bacb1ffccaebbf9c96d2cb41505991cbe039fdcbbd2e4d958b7fab 2 -/usr/share/doc/packages/erlang-doc/doc/system/c_port.html ef307962a029262b6b9c14da5898fa9a6a103597531f3753b730cc2bb481c46f 2 -/usr/share/doc/packages/erlang-doc/doc/system/c_portdriver.html 406f486cd2b86724fcbe81a1178ca7c564dbcb7df82d6ce5485aeb39eaf39d51 2 +/usr/share/doc/packages/erlang-doc/doc/system/benchmarking.html a17cbd38455ed214e6b43e8eb5e20b9deee0d8f1f616bbffc13f7b46f4ac983a 2 +/usr/share/doc/packages/erlang-doc/doc/system/binaryhandling.html 35a8dbc356b864f8c9be1d3865adda802933290815f5d3020ae45a96f0a81259 2 +/usr/share/doc/packages/erlang-doc/doc/system/bit_syntax.html bbf787a160d259f211cfec349f0e11e1619576dc71b473e4bc6280d0ad4d7815 2 +/usr/share/doc/packages/erlang-doc/doc/system/c_port.html c240dad509c43d5fbbdf0009d8f3811a3caf6b0d9c379d262d48fba4a074ca5b 2 +/usr/share/doc/packages/erlang-doc/doc/system/c_portdriver.html 9a09fd8c2fb1469164b4f723921a851e83de74f7babe45e50ce5f58a5aede4f4 2 @@ -2462,5 +2462,5 @@ -/usr/share/doc/packages/erlang-doc/doc/system/code_loading.html c5ebb9805889bf36e26ec16634a75c1ff388f21b609476cf888d32a7c85f95c1 2 -/usr/share/doc/packages/erlang-doc/doc/system/commoncaveats.html 3ff0b04c820a3ecec1e2bfc165fd241ddb27f24df094c6793aae50f2b36cff84 2 -/usr/share/doc/packages/erlang-doc/doc/system/conc_prog.html ef8d5730da80b78d42ce250bb15819884a9330b1ed4cdf0957ccc733b1e1ad34 2 -/usr/share/doc/packages/erlang-doc/doc/system/create_target.html a251f1bfccb58101cb6e7fa27f729abec04469b423e9ec4a0ed3d0c7e31243d5 2 -/usr/share/doc/packages/erlang-doc/doc/system/data_types.html 8d9df0aacc61041d6f39926488a03a76594a440d8ab76afffbae0272107c1560 2 +/usr/share/doc/packages/erlang-doc/doc/system/code_loading.html c425cf5b22385c53fbcd9bf6453f6e019409b411087fdf71e5df11fb9099762e 2 +/usr/share/doc/packages/erlang-doc/doc/system/commoncaveats.html 027a9dbcc7b8e8a08a78a91747d77521d7366c946a3482378406341ec7563f0e 2 +/usr/share/doc/packages/erlang-doc/doc/system/conc_prog.html fb2a5bf9b25bdff676a2b2e416810a31225feed56331727b4a8c54c06b4063e9 2 +/usr/share/doc/packages/erlang-doc/doc/system/create_target.html 3e289555861a2a41f190d4777504ed248819b2e9391ed5d939079b6e5a2d6888 2 +/usr/share/doc/packages/erlang-doc/doc/system/data_types.html 4bec32af9418257c7cbaa1fd504982024abe87e7d0cc79ca31d7b923e2f1f469 2 @@ -2468 +2468 @@ -/usr/share/doc/packages/erlang-doc/doc/system/design_principles.html 62ce1b140db168ce588a6c20299c42232715f677bcc0ec895ae7113bda1540b7 2 +/usr/share/doc/packages/erlang-doc/doc/system/design_principles.html 934b374ab6ce55e3442f89d9f44baa33c6f7f2e277274a134666abd22a294f30 2 @@ -2479,6 +2479,6 @@ -/usr/share/doc/packages/erlang-doc/doc/system/distributed.html 758d3a5d3a8c36c619e16360455465d9f12f716bff159a5ca29f3e4e762ed42a 2 -/usr/share/doc/packages/erlang-doc/doc/system/distributed_applications.html 232ffb3cdf94989a606d4941b49e3e15c5b00ad8d0cdbba25a3cc373d5bde12c 2 -/usr/share/doc/packages/erlang-doc/doc/system/documentation.html 277c5db8f8dc3596bbfbf8963d74b55cadedfb0bb946c11284b4b339b444fd68 2 -/usr/share/doc/packages/erlang-doc/doc/system/drivers.html c964ca200994a917b6bcb837d484be45708d479aa7ed91e5901f1325c4ff2307 2 -/usr/share/doc/packages/erlang-doc/doc/system/eff_guide_functions.html 45b42a5da6e0cdad53c3fa7d6e9c2a39608eae406531df4bb11f8e5ee8fe95d0 2 -/usr/share/doc/packages/erlang-doc/doc/system/eff_guide_processes.html 3fb904b9dd7ace5a7c1e92a33ffd04ac2a76e0497ecff5ff4caf0a20a429f823 2 +/usr/share/doc/packages/erlang-doc/doc/system/distributed.html 0d4c3204dad0bc15cb19514b6d09484423a93d609884851721dbd6644ebe75fd 2 +/usr/share/doc/packages/erlang-doc/doc/system/distributed_applications.html 1fb1220821194766ca3d43b5d73442449cceb58a055dc55a0f0d3099dd5fcc3e 2 +/usr/share/doc/packages/erlang-doc/doc/system/documentation.html ce518b98ba365193cd0b76ce31da5318e2856a8ac1673ff52d67759ec3c4d1ad 2 +/usr/share/doc/packages/erlang-doc/doc/system/drivers.html 2886bd9b8038ed0af95c5209fa5ceb6909d63cdb74da2d66add40319028ef053 2 +/usr/share/doc/packages/erlang-doc/doc/system/eff_guide_functions.html 54d322d8b0e867a65478328b731a1c0d68a2b6c3379ff4ca2783b34e82810643 2 +/usr/share/doc/packages/erlang-doc/doc/system/eff_guide_processes.html eb7ad060483ea6abb5d8874907f0c1a369b2657dd46410b800b167ed12cce976 2 @@ -2487,6 +2487,6 @@ -/usr/share/doc/packages/erlang-doc/doc/system/erl_interface.html f620f55a6a4ef741d3709914b47149f2f5fc73bfbaa97b033585ae6d268b3a8e 2 -/usr/share/doc/packages/erlang-doc/doc/system/error_logging.html 9f3d4c5a7f01962c33b155d9790341b00bddd04ccddf2d2bd87c7762ef3f9d66 2 -/usr/share/doc/packages/erlang-doc/doc/system/errors.html 347e3d9b0d047a218c33aadb4ae657bd4cc575b7e2a2c7bb5fa9a53d0e690a38 2 -/usr/share/doc/packages/erlang-doc/doc/system/events.html 45356b488bb4407fbfd5e5c8bb0317d56ba66246df868b2ada11155ebb12ed4f 2 -/usr/share/doc/packages/erlang-doc/doc/system/example.html 77d35c0ac95dabdb5611eb6940231a63e1206641e16e246ff79fd09c428aad73 2 -/usr/share/doc/packages/erlang-doc/doc/system/expressions.html 405a38f40103f3780dcfb4427ba79567bbbd80fd34321e74bebd2c4ea5f7526d 2 +/usr/share/doc/packages/erlang-doc/doc/system/erl_interface.html a50766c4e609965f321b80d6ae623bc501747a55d2e06ba12caeac6d3772a7a4 2 +/usr/share/doc/packages/erlang-doc/doc/system/error_logging.html a3a8154dedf1ee3ffed9278b4ed75f30645a73bd6a16309968d4cc48b5c9b2cc 2 +/usr/share/doc/packages/erlang-doc/doc/system/errors.html 0888a98d3934ad906b9d0a331a8ca0dbc0c65a384f33292e0f29be8c1ec5dff3 2 +/usr/share/doc/packages/erlang-doc/doc/system/events.html 7ec1db7dc376795f9300c048337e5f2625ce028881513e4abdc2e1c43728469e 2 +/usr/share/doc/packages/erlang-doc/doc/system/example.html b8ec5b76c86e93dedd49de606732647320e86a071d30aad5c725d5a1f67e791e 2 +/usr/share/doc/packages/erlang-doc/doc/system/expressions.html a838a0b07a909bfb7039394a578765450000625e8ed8174d32b93130cd3ad08d 2 @@ -2494,2 +2494,2 @@ -/usr/share/doc/packages/erlang-doc/doc/system/funs.html a78081d620336adb53d032e9083655fe374a3a1a7423d257350fddcd7f0e3bb0 2 -/usr/share/doc/packages/erlang-doc/doc/system/gen_server_concepts.html 19b796dcc011bdf5340b2bc87b183ee1c24b898476749ee35dab9e0ba37e7816 2 +/usr/share/doc/packages/erlang-doc/doc/system/funs.html 0e4e9ffc9e05f7ebd98220f1be7a88213a19f0a01c9b9c6431a20e199208125d 2 +/usr/share/doc/packages/erlang-doc/doc/system/gen_server_concepts.html 581166473a5c603e8a6975eca7674ca519d6235d73cdf18e5e04316a3a4aa59e 2 @@ -2498 +2498 @@ -/usr/share/doc/packages/erlang-doc/doc/system/included_applications.html a74886bf907cf67abc25529455b3f9acefbfcae92c33fa39d2f1f34806f88531 2 +/usr/share/doc/packages/erlang-doc/doc/system/included_applications.html 56ebfe1d825983ea00918e856b2d03d6a891291310585705880fcc415766593d 2 @@ -2501 +2501 @@ -/usr/share/doc/packages/erlang-doc/doc/system/install-win32.html 35b7923b7463be4c44e0e230ec615e6f13ff43bc1d0f48a379b0eddd25b103ed 2 +/usr/share/doc/packages/erlang-doc/doc/system/install-win32.html b264a11bb3ec713353704ed67bcd0de055b15b4b8a73eff6e71a4165fa03dd79 2 @@ -2504,4 +2504,4 @@ -/usr/share/doc/packages/erlang-doc/doc/system/list_comprehensions.html 6d05a05b4babebd329cb35d88f17c3a9d40ec383dee6435ebc8be2bdba4e8a5b 2 -/usr/share/doc/packages/erlang-doc/doc/system/listhandling.html 878a4b6ebbb103f5f9830416a47cccd0ce010488131e4834269c13f8272452ed 2 -/usr/share/doc/packages/erlang-doc/doc/system/macros.html 63c857aed08d2a9d03b0920cdf8e6486fca745bfdbc008622ccc35b910bb5f29 2 -/usr/share/doc/packages/erlang-doc/doc/system/maps.html 9a57b27bc05204b752f53a2431b3fff183c693e19c89caf1af5ae87942c41121 2 +/usr/share/doc/packages/erlang-doc/doc/system/list_comprehensions.html 6856ed47bfd1559129a309067ec119257b4164d36f50e8365e367b1c1f2c802b 2 +/usr/share/doc/packages/erlang-doc/doc/system/listhandling.html 2dad7ebf7d4cd89c977d7e2cb12c7adfac8307f1a2ad814f5c91e146a40b09df 2 +/usr/share/doc/packages/erlang-doc/doc/system/macros.html 27769020ccf36403aeb6c3f809cafcf9ee7f0dc2e9964a7eca06b3b641c098cd 2 +/usr/share/doc/packages/erlang-doc/doc/system/maps.html 5010a427e41d8018369cbfb283fff9ab3cf8b7013ff68a1461fa635597575ec7 2 @@ -2510,5 +2510,5 @@ -/usr/share/doc/packages/erlang-doc/doc/system/modules.html 9f9c0088e2d066fa061356f2540394100a2bfbc3c9940827fc78ddac6c61bd7c 2 -/usr/share/doc/packages/erlang-doc/doc/system/nif.html 28ad01ddb2e331cba280aa3d1eb4f89e610e3e8753762f6191be4a92d24734ab 2 -/usr/share/doc/packages/erlang-doc/doc/system/nominals.html 87dbf3fe6a418e7615809f7c3d963192e69ab6a9174b076f31bd7379d685d3b9 2 -/usr/share/doc/packages/erlang-doc/doc/system/opaques.html 55d72579526539ab6313dffe2854e27abc60028ef2715e4eba9c341200339370 2 -/usr/share/doc/packages/erlang-doc/doc/system/otp-patch-apply.html 1e37ee27d239393d473dd729be8b923de127efe9e3831085e87a31f0577eab25 2 +/usr/share/doc/packages/erlang-doc/doc/system/modules.html 182b51bb31979a28994a5c49122f60c2b05c3ee3ff0e141dcd0cc0203201fcde 2 +/usr/share/doc/packages/erlang-doc/doc/system/nif.html 2f66ae86ebd7546e5aece556cfb5ee91463e609e0f8deae79a378693a7578957 2 +/usr/share/doc/packages/erlang-doc/doc/system/nominals.html 44a28c11774176fc00800d061c5520b300be8747fc54c3d2f71ce5d0e5bb095a 2 +/usr/share/doc/packages/erlang-doc/doc/system/opaques.html 3a7034117e1712d3b4292c208782ab3d8ce75dcc37879c0da2a6f27ecb884443 2 +/usr/share/doc/packages/erlang-doc/doc/system/otp-patch-apply.html e3be27779f1eb29505c421eaeebc0b96e3105fddfa1bc039c997777bf6aa048e 2 @@ -2516 +2516 @@ -/usr/share/doc/packages/erlang-doc/doc/system/patterns.html 6795fc4fcbe3d4cac4f2985c4ed9c92ac274aa9c08d200c7f9dedd5e41331ed3 2 +/usr/share/doc/packages/erlang-doc/doc/system/patterns.html d9cfb487aa41310281186ed616c5985882dd7f33bee9e9272557264b8430b7f1 2 @@ -2519 +2519 @@ -/usr/share/doc/packages/erlang-doc/doc/system/prog_ex_records.html 86210c282015bc1918232279f076d6821e71b16a1c0a0c823f0a2a3364355cf1 2 +/usr/share/doc/packages/erlang-doc/doc/system/prog_ex_records.html ef4fae28b711e4fcdcd58b3601596db6c945f1dbe3bd4275efa73b89749b0309 2 @@ -2522,4 +2522,4 @@ -/usr/share/doc/packages/erlang-doc/doc/system/records_macros.html 1a5bf5f58207d15a1f28b8e566a9048fb93b54b7df239baa00052b4902f6d02b 2 -/usr/share/doc/packages/erlang-doc/doc/system/ref_man_functions.html b0ac57152c52b4bdd258b31c9d1b0782b8ce6b5166e1cc74dc898b3ad5f46933 2 -/usr/share/doc/packages/erlang-doc/doc/system/ref_man_processes.html 46246149e598322f91916c43fc636e99e2e35befc6cfd9c09989c0f29215cc38 2 -/usr/share/doc/packages/erlang-doc/doc/system/ref_man_records.html ab773ca0a61a3edf0e8bc9013870ec6e48db4d0f784ea1933b9a42ef8ddfbdbc 2 +/usr/share/doc/packages/erlang-doc/doc/system/records_macros.html ea015d0776bfa20c4235f4daa9d7704ce0d0cbe5c76e653468060179a4e89fc0 2 +/usr/share/doc/packages/erlang-doc/doc/system/ref_man_functions.html 963873184adba78b3c7023e798dd76844aefa10f13909e0529029fecbacff2bb 2 +/usr/share/doc/packages/erlang-doc/doc/system/ref_man_processes.html 1ca26f138a10f0881a29687a00de346f57461ad17039d407fe4cf5a183665999 2 +/usr/share/doc/packages/erlang-doc/doc/system/ref_man_records.html 1a6833b1b3130235d7b2e488d0afe05ca92fe3d60fb26b4a2a1557665acf9e34 2 @@ -2527,3 +2527,3 @@ -/usr/share/doc/packages/erlang-doc/doc/system/release_handling.html 7eb435678618dfee03dae87245c1645e37b7893b1630c5b11213ded8496ff580 2 -/usr/share/doc/packages/erlang-doc/doc/system/release_structure.html 1a4290dfe9dcee680ddd0d9025d416664d93b868fa8d6401df0b427c263fdec0 2 -/usr/share/doc/packages/erlang-doc/doc/system/robustness.html f69ba4871fc3e9570cc26b851b1e974a182955a242d645b51287e1b5c6edb063 2 +/usr/share/doc/packages/erlang-doc/doc/system/release_handling.html 62d2497915f6f388a01cfd8a37fd4c42e205bd5abaadc70b86ab09901b2c9513 2 +/usr/share/doc/packages/erlang-doc/doc/system/release_structure.html 018e53fdcf6bd7791445248d8211bf2696922b51bc4b1bcf8f40391a3ea6af3a 2 +/usr/share/doc/packages/erlang-doc/doc/system/robustness.html 66aae61745189c9bbe1ffe1dfefabc79f4953d3221b0f335060fb0af875e7acb 2 @@ -2532,5 +2532,5 @@ -/usr/share/doc/packages/erlang-doc/doc/system/secure_coding.html f3806f1e17643db3066a9f311840c51cbfc6fd85205815fa5fda00d25a810c80 2 -/usr/share/doc/packages/erlang-doc/doc/system/seq_prog.html 91b7f04dac57f75c3281198a37403f42b6f0dddae4b6d3793cf744c8d925f8f2 2 -/usr/share/doc/packages/erlang-doc/doc/system/spec_proc.html b02e46572dba1afd09d3efdb8507970e356b23bb4e4341fc09486e7eb25bcae0 2 -/usr/share/doc/packages/erlang-doc/doc/system/statem.html 676c2202faa71dcac2e563f313db8a0ae9aa493fc280aa28944fb3f70aea7019 2 -/usr/share/doc/packages/erlang-doc/doc/system/sup_princ.html b585bbc9fdd1ed80a2f1b676c51570795c799e5f942eb3ab42d583f4ff1b9f93 2 +/usr/share/doc/packages/erlang-doc/doc/system/secure_coding.html 793a00294e7cb64507e2ccddb8f49ba2bc0cbc494e73a40fff518bf009fdc032 2 +/usr/share/doc/packages/erlang-doc/doc/system/seq_prog.html e45df0cd21a8c02e5f3385941c773cd60c4497ff99676f8a6825f9876e57378f 2 +/usr/share/doc/packages/erlang-doc/doc/system/spec_proc.html 9fbb94efc226cd8508026d5c052252a4623a743ef739a39465ecdc0a2cabafa2 2 +/usr/share/doc/packages/erlang-doc/doc/system/statem.html fc14abf7853c9a137a0200291e250280429c3edbd3ae787ba77fafd26b1f426a 2 +/usr/share/doc/packages/erlang-doc/doc/system/sup_princ.html d280e3b03bdfa1b4230b91060f771094ec1dd0b08418f0e489ebc3df3e5705db 2 @@ -2539 +2539 @@ -/usr/share/doc/packages/erlang-doc/doc/system/tablesdatabases.html 913e32518d77d5bdada26221fe78219903b3b0e6c82650aba1784ae3c2bb6301 2 +/usr/share/doc/packages/erlang-doc/doc/system/tablesdatabases.html c0041ed644cbe1fc063b8de000d1f6a692b942ceafa156b1a4dd3e9ee53ead4a 2 @@ -2541 +2541 @@ -/usr/share/doc/packages/erlang-doc/doc/system/typespec.html 2877f1319afed03a5808dafddc93d5fd7436240e28413d33db4335a191ed05d3 2 +/usr/share/doc/packages/erlang-doc/doc/system/typespec.html f916f9cd1e711d2a304cc84fc74048634876d1070bb618dba26ab30412d56f4b 2 @@ -2544 +2544 @@ -/usr/share/doc/packages/erlang-doc/doc/system/vulnerabilities.html ed16647afccfbd6f0b2c3e0538738eccd8d1278cc6e24bc1699e0d4e4576e600 2 +/usr/share/doc/packages/erlang-doc/doc/system/vulnerabilities.html ffed6e66bdf7305467b4dc210585a5ba6acd7e3d8e862e8552320573097bc7aa 2 @@ -2549 +2549 @@ -/usr/share/doc/packages/erlang-doc/doc/upcoming_incompatibilities.html f6d54acadf4bb978f59b07063f4252452749fa72d5c626d9cea2658fe64768a2 2 +/usr/share/doc/packages/erlang-doc/doc/upcoming_incompatibilities.html 549af0c54a8eeaac8633f873f87f5fbeb269e63bb5fe7add194d5eb97f29e18d 2 @@ -2559 +2559 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/alt_dist.html e0149029224ce26bc0502c3d2c776677ff1816e76bbd13bc561bbe3835802a60 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/alt_dist.html 04beeb363a19ad1706c223916b0b2a0807174c0bbe4b5b48c3d83f531b24480e 2 @@ -2577,3 +2577,3 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/automaticyieldingofccode.html 1504b761559d70d4eb1ef68f27bcf00cc118e4c95ec80da074b7be8e740cdebd 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/beam_makeops.html 9784b4ba7a1700835eb0338af425eefc4c22a6a7b01e78c022a1c841d1e383e3 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/beamasm.html 821d3989d562a274f2fdcb94b389e3158d0abb6a77a79ce772b95eee050faad5 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/automaticyieldingofccode.html db8c6e74548f04a51d79b4d0073730a1d2db4cf8694d4d8b520ff97f42253644 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/beam_makeops.html f4452e2f1b7108011a0f712fa8f4425d7adfca51269a114278e157b726286822 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/beamasm.html 4a1e851bf1a4ba3b0e55fa537db2df7ab3f4552d6021232b391836584bc638af 2 @@ -2582 +2582 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/codeloading.html 6d3ee62e5b72048f872947738c1275320a725994b4744782c8c9377c61dfb6f1 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/codeloading.html 2493c9410cea3703ad9322ae4ae94ca5bd57947023049fc49a9622f3bc724d97 2 @@ -2586 +2586 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/crash_dump.html afd0b73b2943bb515cda9d8bb4c759aff142099a15c6bace37fdbfbcfdbaa463 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/crash_dump.html d38d99d3c8c3c6bca9aff73a36d2df1f924b85d67bf2777999acc93a986302b4 2 @@ -2598,2 +2598,2 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/driver.html dc072b4f53a8a7d0de17264d9751ee71da4f042fb1f47be2e88c06d54eeb79a1 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/driver_entry.html 6f04ef3a39e19e05c67b6ce0518f4012a47aeb552e717a917525180e21ebb73b 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/driver.html be4607ed2e8755e1030783af3e37b4bbbb61dc19ac5fce1d980436412eba2baf 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/driver_entry.html be82c04783cdd620932f17ccd9cdcf4bbffd3107b35438f656ce8dd7421f25ea 2 @@ -2601,8 +2601,8 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_cmd.html b017bb8b1cc55ca84d38a2a4dd6fee8e38c30e69f97951793788c9d0756f0804 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_dist_protocol.html bff081bdc7aed1d454e71ae641c726af1d30b22006d55605eee3372bae5e5174 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_driver.html f1855860641f59320ee5559f48c564607b97f454662365c7a79e574365bb5fdd 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_ext_dist.html 0f64a8beb9c762631ba87e88b0836119799474eb2dc37b737bb11ccc1605b410 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_nif.html 8a9dbb3d817a3a17e1ee2682c4b1a0b2759d9ceb152d00f19764c23a0a7f90d4 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_prim_loader.html 062a60c0e5d7f8f29312529fa4010c41ad810ed8f68892a11fab1c64316e8947 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_tracer.html ea57cf048b63fdfc6041ccd25e84b1711be0f99043dad25738192d37da23fa9b 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erlang.html 654e32992cbd895e6aceac05e14db5d485ee8ac2113553e890475aea8fe9de90 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_cmd.html 4ad2728f74cb3e4e4624c90d2d0862b65afec3dbf85ee677228f6d45f8f79a19 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_dist_protocol.html d6f4858b84ac16bfc382e1fd20a0e0220b7ad436d3b71fa015fce43f678997d5 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_driver.html c7e89befbb604cc38c003cc36fc2ce90308db49986930ce0c72e6fe45a6ab3ff 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_ext_dist.html 4c74757a51debabca127d55ef21872801bcc5459efa77497d4966b19f27f27fb 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_nif.html e4fdd5830e5c8d121e3b4f1710ac0d6505efe7742833e1947fd6792b8a7903d1 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_prim_loader.html d525a82da2bcb714c2e427109c5f5f30ef17649f838898ba73f33065057fa50a 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erl_tracer.html d88827c45cae9e908e7ac5a07744b8ada00b183b10466c3a966b5499c3d08b37 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erlang.html eaef92ec151808daca34cfcd5eb4bf1842bc1f9862f3d0473ff673e599581cf4 2 @@ -2610 +2610 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erlsrv_cmd.html cf57912cf3f5aabde2a46a709eb4504ea688b0647c8116fb768dc84df4175fca 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erlsrv_cmd.html 9f373d2bf3b556b45f987e051d8a1f3e2e6ef378a94b73a4c36673a3a837724a 2 @@ -2612,2 +2612,2 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/escript_cmd.html 9d9c689c70934a284b728bc5253ef1fb8c9158623d204eb1b1d4dab594de0bc8 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/garbagecollection.html 53edf84ff2a7912e2b5f9ac348042027305b420af86d16dea0379c26706426c9 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/escript_cmd.html f6be5e5358b6094616ff48bc40d1139a30f57cded4aec89557bc4f8c71a58553 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/garbagecollection.html 7c61a77a8a42cdd561b7b9cd640d9187abab65787bb4dacbc61f075706643b44 2 @@ -2615,2 +2615,2 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/inet_cfg.html d7b3d50716c89650f877798231f2306661c5f1a4c2b4f71b98c00dba3773320a 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/init.html 0db5ce7959270558000424b6996f120f783c891b68f4b45061670a7f3a50ecab 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/inet_cfg.html f87aca151159dd4a83b7691ab8d907b9f16abae2e5617584fee0ba868ed1b92d 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/init.html 935976ebc320a58438b33755ecef9c7d2086f4e2054703d2234b3b218f5367a8 2 @@ -2618,3 +2618,3 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/match_spec.html 91752fdbf751b5320e0b540632a8403d2b4b17da20c76c460bd7e39546e76edf 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/notes.html c1f6ec35885ebb59a28af4029a002a1e1338050d9e3e37fb80a1890b901d1428 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/persistent_term.html cce4302b79fcc62ab25df2fe24929770fa3ec645e8e1dc56a588f8127dcdf279 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/match_spec.html 4a509b6df57061e86c31da784a49871fd0fe3f3defcdda6ff30d3026ea03ff4c 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/notes.html 405ed4217384614841f75bda925c9905ff04d610dce3dd37480e6ff95024823a 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/persistent_term.html 562ea70f36a85fbaf9fee9f08e2f673d338651bbbdc9774f4e2963a6805e029d 2 @@ -2628 +2628 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/supercarrier.html 8997da25a22d277c389855ae10c8bfda1b6ae1f9ee7fae9816a7b8aa54e10025 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/supercarrier.html 49fb3d36987c48255cd21d8640609444b46404d2b0b5c82b74178d32ac479895 2 @@ -2630,2 +2630,2 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/time_correction.html 5dc2ab9301fa97f15d52ccd335dfa4fbabe788e018d7e50f417587481a1a4852 2 -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/tracing.html 2df7f281b8c1c0c050f5fb2f61dcbbfb8c005ac4d7ce4c2d07d26979bc74490b 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/time_correction.html d660346e6cab2e82680781c85ad8b7b917ecfc5ccefb5c76975f5a8b21855e03 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/tracing.html 00b479721534a2847d457dac3adbb493c75c60f374db95b56185b83b86106658 2 @@ -2634 +2634 @@ -/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/zlib.html eb7e4edd8aaaab2208c9c1d4c9f77d2d7193d2cb3f2bf38aabf2b12f5ca9a794 2 +/usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/zlib.html 8fae526bdcba27c6fa07a72ea33321943b1c33a4263610bb5add34ade8aae059 2 @@ -2643,2 +2643,2 @@ -/usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub 9a7c7d58c304058a6ffd057fc1b80b36269938957c46c6c13050a042270dec15 2 -/usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1_getting_started.html ab20bcd6c8810a668ab8ffebdc61bda8f99179182f357f5122d7a84f9704b8e3 2 +/usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub e78e605236f53e6eb3ece0e9e135a9d517cf091fcc915e3da8126562cda9289b 2 +/usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1_getting_started.html f8a3e7c9a1eb6b1643358eebefb3d1dd0e82906023e89de3240c12cbfe7231a7 2 @@ -2647,2 +2647,2 @@ -/usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1_spec.html 78903355dacace583a6383d798b932d68d091d25253e8f74b67a4bdc5747ed94 2 -/usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1ct.html 2d7360e167019b8260af0b820a1854341e6a2804d6fa6d1912981ca8d30909a9 2 +/usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1_spec.html e1c4c5dfd062b97edd6cb219cda2a551795b3bc3ae5d6234c4ee81ad85182b47 2 +/usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1ct.html 37766006a3fe30ab916a587cd5b05ab8f01dabc898da5e5c4cfa1b51f7ab45d9 2 @@ -2665 +2665 @@ -/usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/notes.html eb30d1adf92a6a193792773b9b006b3f25cab769e7f06978a631e45638487828 2 +/usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/notes.html 55588e2d2af9e86bbd32c346ec085790972dd9f8e3b7e9acc090bee150f8aa6c 2 @@ -2677,2 +2677,2 @@ -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/basics_chapter.html 0e603c39a15d61cd057c6535711e84bf357df9031bd8855986affa7eb5ccef04 2 -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub a1acd404f6101951bdf79cf64eb6acc9edaf7272dc874283531b9aae859cdc9a 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/basics_chapter.html 7f08ba9dd67f5315474625572559a6bb8df79f540ab0fd9f08cf978a9e44065e 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub 1956ce860d07d50b2317ab8cde1ddb24e195fb3b08c0e8ae2a478fdedfa693a6 2 @@ -2680,3 +2680,3 @@ -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/config_file_chapter.html 5757990c150003b231e09e97f44c573674ee9a317daeedd0f58c87e126c85026 2 -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/cover_chapter.html ad8d62eb2e289a3297b1f95ee9bdd94b3224857be584f3a386b3e096eb4d0716 2 -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct.html c5f6d67d08a1f89e7d5bd34a2d019b604bdc4efaebe1782bdf2e271e1061f440 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/config_file_chapter.html f030b260441199b3c0ce1690b6114aa9e361ac16704bade922395f7f3fe124e8 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/cover_chapter.html e4e91ff763ded8f744893b89af3b558b4a1fa9eaf0476563d07627569881b7b2 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct.html 7bea9787d873f0b6c903cbe8c30d0eb5f30935c10201ee53144e820b31b2013b 2 @@ -2684 +2684 @@ -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_ftp.html d1d5b079d84b5c5c475f29db2f6677d944ab3ba4082c5f27e0dd747eaa3beb8d 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_ftp.html dbadfa8b618e5fce0daf066827b995efcfaec69427174164709197bf9eaca238 2 @@ -2686,6 +2686,6 @@ -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_hooks_chapter.html 83edf9045e46d2ff45a473127138c0e981b07999eae06f9a08e1de26cf57cfde 2 -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_master.html 05ea7f4e420f1f16a1b7450563be0785ae4f54b2b474932b63dcabc0a0d6e15d 2 -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_master_chapter.html 496e8c533f97c90aa8325830d91d4d9f141754a9b1436f813ff27a5f6f2b9ddd 2 -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_netconfc.html 29523be29caa4c1b236e9670ca2791861ff2331c854cf4239127320b7fab0f99 2 -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_property_test.html d4cbf346606e3504710ab81339ab70fae3c6ec69b13568c0024fddf0050d718f 2 -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_property_test_chapter.html 144c55fbbb90cf264954a073b3842740dcb82527eca5c41b2f15dc8d3436465e 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_hooks_chapter.html fdcda68b44e5a65c5d0f6544fa3d5d90a13849200ca0ecbebf1d75b148acbcbd 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_master.html 3bec56206bec14ae723d31b2d4ae4d4d3bd91bd02968914031d66e10592eb373 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_master_chapter.html c21e7b1ebc49fc693948481f6fdae3428246d92687acf55468240963aeb8dc2a 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_netconfc.html 7e4c9993aef72d1b53bc0ad5012ac8e1e30e30eaa7d7ecb66e64dd1636920c95 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_property_test.html 7bd67d6e288ac8f5a10055e30540d9f7a6b057c1136882d7ebc34ca9404125e5 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_property_test_chapter.html 0f853a05776d0b83bc29246263d5a3ca1866eaba0ab78fc6eb8940b4e269ac00 2 @@ -2693 +2693 @@ -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_run_cmd.html c9f7b602a724af922350873ea891f88c2fdb0bd68cc8012afb908000d9d2e24b 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_run_cmd.html 0c56a15ad6621a4331cedba84fa05682553e7b7d3decaf24a5d4ca5f24d1b97b 2 @@ -2695,2 +2695,2 @@ -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_snmp.html 6804bc266ae61fc8a023d9587fc07688e4f0eb74d4e98cf0d024b3d95c4d311d 2 -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_ssh.html b60b172a4abd410331728150ef600fdf4a7ebe7a69431f63c014502d8dd34578 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_snmp.html e98aeef8eccded8f62c939e2d9c09f60e4f4ff6c1fbb681fb1a0978d7b7a1908 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_ssh.html d0dfe1cdaafc583c46589a4f0a524250ccedf893ab0f97523068a25b9c661fb0 2 @@ -2698 +2698 @@ -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_telnet.html 4d4a67b27e2d6e2bcfbbad83ea3906613885b0362b792ae18b914e875f4f808c 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_telnet.html 567e8ba7666ee267c368d0c793fd08140cd57a6e336d687b94d3e1b7afc00245 2 @@ -2700 +2700 @@ -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/dependencies_chapter.html e4346c95394564563a75e5f3de1eae24a059f559ceeb7cc5afc3de6e6ee6c159 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/dependencies_chapter.html 0fc16b4ee6d4117c052a5213cdc90440b9e595bce96a679b841d7e4f19bd2dd9 2 @@ -2711,3 +2711,3 @@ -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/event_handler_chapter.html 39c69694cac2d670faaaf447ad0c07219c754c66f90542b4e0a2a72b3e8078e3 2 -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/example_chapter.html 4c3acbd3267567660077c48e44fc3d154f2a30f2f3a45a6f7cc190f40565bd56 2 -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/getting_started_chapter.html e01fd13b03b4f3e67c20aa4063ea3f2ae30532e207f73d557e171579bf2611dd 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/event_handler_chapter.html aae099662938c54950c35d1979563b20a89e172c8a0b72c7f338746eca26e681 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/example_chapter.html ab6f9c555b3dd521f8e0ab70b8026f77609cbd1f5aa7418cf0a795ac54dde16a 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/getting_started_chapter.html 378f14e206e50c2f05b4deb8b0dd9b813727b6400ff1bc2782f74a8e08b7d38f 2 @@ -2718 +2718 @@ -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/run_test_chapter.html 793da9c3142783d779fad5b79f77602ec8f526993d8151382d006be5f15559b9 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/run_test_chapter.html 9843302b593f262377a63101dbc7424eadc9cedc13aea024d56b39b643d9e17c 2 @@ -2721 +2721 @@ -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/unix_telnet.html b82cd1a6d16e683e3d1d94bea483d29f7db852d868f03fe9f566fea37b4902e4 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/unix_telnet.html f3137e93cf844f9cf6ee7d740cbbc672814f43713211b14d4cbb064ee6cac0c7 2 @@ -2723 +2723 @@ -/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/write_test_chapter.html f6e07cd96e07e9ec87ba78fc6c558390c5f79522b71606b98e58f22948b51f78 2 +/usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/write_test_chapter.html a0fb91579df5cdac844d33e4d40efe3670ab2b3407d657689f620751422ba0d6 2 @@ -2731 +2731 @@ -/usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/beam_ssa.html d58795ef0cbcaec8716ce1b42dc17925554144d468593c5a8a1143924956d084 2 +/usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/beam_ssa.html e0fb6715ed284584202dc6d7a155f8b4aae7fcfc7aaef397ec1fd618369a0ed7 2 @@ -2735,2 +2735,2 @@ -/usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compile.html de7b5bf9392181088b78ca7fdaafb5b2ae20fcc98f1eb8171109654eee92f977 2 -/usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub a3842bab1fc12ded738496591ef6e04f7838a5aff116b341d5b894d48b73bbf5 2 +/usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compile.html a3c840752f732cc304d88ae78841622a28ea430487d4c34a090488397c6e9284 2 +/usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub e353e7b92d4ff9ad0447c4b00ddd449a0c5d7fb987c192632833943813c8ccd0 2 @@ -2748 +2748 @@ -/usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/notes.html eab759fda230365f3039980caa164c172f7990f9dfe1795633844d5c85ff0ecc 2 +/usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/notes.html 114e0c720506da593bd49b2fdf9825c8ebe334a24ce61c42a065a2efb23f94b4 2 @@ -2750 +2750 @@ -/usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/ssa_checks.html 8b36bbba6abdd95e033afa82920726f14f405eab2dbc031c6f35eb8d78ec2629 2 +/usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/ssa_checks.html 76174bf88095bec8e9ba3781e3b86f6563fc0a5593e63086dc6678812fc3bd13 2 @@ -2759,2 +2759,2 @@ -/usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub 7ba9e8007a5cab501a5fb13ce59eab5d4c4e36fa3d60623e101b8bebb8e112f8 2 -/usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.html 507276d0e8c8e25cb5656019ac55086a4fa48e1ef666bc21346359fcf7b39902 2 +/usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub 470bf69ee9c02f37a15c036f2fda22b36d06656c823d4304e011ddb733d029c0 2 +/usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.html ebcb9ecf238462220a929af65e0a3f2e70045cb1e71fdc8883532e1974a6ce40 2 @@ -2772,2 +2772,2 @@ -/usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/engine_keys.html af7870554f1a016a883995583a5c40cc59dd5028d34d0517e8d56e11e5dc425c 2 -/usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/engine_load.html 86fa4b68b6838260f63b873ca6a7b5542ef1a7536987054bce003064ca66c9b5 2 +/usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/engine_keys.html a2ca1256269f2e2fc7379c64f715e71ad454eec56ac7dc4e9abc4a1cb66ce20e 2 +/usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/engine_load.html 3b519eafd28eb67e6cb04822625b74048b105c42b25918588e4357f1ec800de2 2 @@ -2776 +2776 @@ -/usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/new_api.html db65132a45faab5979fcb7621a4b577b38dbb0520e699f612deed06ad1c897eb 2 +/usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/new_api.html 155e9625705a99a2d10d6845e89cfec2b98c6d477a873129a73b15d97b67a267 2 @@ -2793 +2793 @@ -/usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub 09d9133014df567484aa1ae49ef04ba4a10aa48ac8d2126e757933aa1586b1c5 2 +/usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub adc1f4f9db725a1f8b6f3c0227aa3775088103dc8a2084f6fe93ee517b4c3702 2 @@ -2795 +2795 @@ -/usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger_chapter.html 4cea7a595c26fba6c10986b4e7b57ea2a996c3822e97152c9539eb8227b29d8a 2 +/usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger_chapter.html 546ebe05a43b93aa030a7525c747e28a3cfe83d8747eea8761ca35bf2fc8ac6c 2 @@ -2806 +2806 @@ -/usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/i.html c120bf06b11f457cde756ee2a8240c233a9c59c21ca517ef8bd43453c2c581e8 2 +/usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/i.html 9c553a7626978d85244c87e4101166e5b5e99b3a9eb0de06d7bf7e7ec0314712 2 @@ -2808 +2808 @@ -/usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/int.html 244455cfd67cb63a28b8250c2abb6a473814c37094ab91f54ab69c3b6e3667ea 2 +/usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/int.html 0bfa2d027b6faaada553c66665c739c2e8eb82c00be8138b44b6ab85950a1e31 2 @@ -2810 +2810 @@ -/usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/notes.html 20304ef04678199cd60beadbdaf566f85a67d5d861f5b1f10a5d2c28d9c740a0 2 +/usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/notes.html 50f5bc6727bb5666afcde1897fe3f5915281a456eb52266b174b9ad9ee2a2d33 2 @@ -2819,3 +2819,3 @@ -/usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub 9683698790a0168d5aa75d66c5e63ee391ab59108ceb28ded32107c28f74db0f 2 -/usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.html 9e6a1b1b1504d22996d0effcace3cba19c9b6321b4c5a0394f89c40a061a0258 2 -/usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer_chapter.html e1891f17a4d5090ae407420e04421b8bae6266991aea6e578bf52696eef25cea 2 +/usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub 71b8511f5fede717d9ab55e7ed05db7b82f627e836750d57036d7a2564147ea6 2 +/usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.html 53a5ed001861bca79b5df63bea2330ce96d2e183102d7193c4a1b482ff0ace92 2 +/usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer_chapter.html 5f5a8df71900a3b83ef5152d2528bcb2b3d75fa4ee5db4f5a5005fbdc4b5a8b5 2 @@ -2833 +2833 @@ -/usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/notes.html ef36c8449e69af3409e2f840fa81b4b08628042424d24b1192e819906ea0eb89 2 +/usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/notes.html a4bb10a6bd96d8a5e5939695094572836c490b431594a5969e5f247ec8e82f09 2 @@ -2861,5 +2861,5 @@ -/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub 5ab4b85f0ee0bf6201ec2a8e7c5dd4a0a42cc552c3daa8e880614cbc94c431a3 2 -/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.html 604b16bf3978b9b681f1e9908f5d58e0887b4fcaa54ba4e74f0c506d9eb7b546 2 -/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_app.html 14aa262dedc5f8290f99f6a1e3dd749451ffb3737efa6b00a479bec6f4674e3c 2 -/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_codec.html 5408aed221179b4a188bb179e44e7e77dea598fc36503d94c5dfc74356052ca5 2 -/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_dict.html 2a5056aead7865c9576163009c518e73c6faba21d971dd0017850eb7088c1415 2 +/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub ea53c8d93e5527aad1af1758c782b9c6319391060dceeda962f1bc01e0306f81 2 +/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.html 4498e01af2f0172d6033cfa591cc905e15aca48131612c89c4241184af9e7688 2 +/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_app.html 33c34e4adf1e2c59c6be4451d2b6f4dbdf2d8086e9aedeff92cbbe2dd0fd668c 2 +/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_codec.html da5c3d0b1003fe5d2fdf216485d246160d87d25ab6242d528eab7e2ba06a4c22 2 +/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_dict.html f8d0b17b7c10edd26f2919ad9af1c3dd252c5076fa6d12c79e179020a620f67d 2 @@ -2875 +2875 @@ -/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameterc_cmd.html 9f895e1431a70b44f22be0e5356f7ce9d19ce3e2eea6282595789806c2d96e24 2 +/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameterc_cmd.html 93a0e9e7536cedf195616da4112c797547c53892f396d54ba6df89b633b0875c 2 @@ -2887 +2887 @@ -/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/notes.html 18e9408a5ce9c48bbb11622528d214bac8626ae0eac1b5db3bc98b00e15330f1 2 +/usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/notes.html d46cc837ba99983b269af32447f44e727bee2cfd82ac8c20df755244b059ec18 2 @@ -2911 +2911 @@ -/usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/dist/search_data-B18D77D5.js 112bf14fa46d6e00163e66a2f540db2ec61484e7805b8fffb351a8c84e31504d 2 +/usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/dist/search_data-0F342CA6.js 083c1b884a3ce41148951fa103e54a6e4fd821ae837d9987fa50ffc52a66e037 2 @@ -2918 +2918 @@ -/usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/edoc_doclet_markdown.html 0b18c90c911130d9b8aba606155d366114874249be2be91aa36cbafbe32fbaba 2 +/usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/edoc_doclet_markdown.html bec02ac67b9f9a1f16e20fa38c468b5d7aba0e039cfcd716d53d8dfc16c70a83 2 @@ -2926,2 +2926,2 @@ -/usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/notes.html 7471ee92a7c85bcb311352c080c6774cc7e44563562fc64aaa7160d4a6f6a9ec 2 -/usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/search.html 0f09bfc23416d9b53ceda149542e8946664f1a0efee4a508f1f24c7a8dcf3796 2 +/usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/notes.html 656bde2b4682a896b0ae12ec8da73550c5c635be035ec12446d3b4a0f0e80eba 2 +/usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/search.html 39d77f602e50d7dd61faab64068810721c2fb56da0ede14b6a54c0ce6d950459 2 @@ -2945,2 +2945,2 @@ -/usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.epub 6bb21770dad3314a393a087d03ea4fff651117c9aa33cbd3c1b60e94f268f29b 2 -/usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.html 09738a292094fb4e7d6f6808c3f87b0cb37f86138868e3a8557aacabacda5c75 2 +/usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.epub ffc0afaa9b1ad50db401800a01310ca255a47bf7ec1f79d6ba15cab4ac236dad 2 +/usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.html 214852270fb054870597b22f95789d356fc054aaa25fbee2d33255250dfbead3 2 @@ -2966,6 +2966,6 @@ -/usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/ei.html 7b98d19e6a32c975878ce143094232235ed1dee30868a3efda97e409a58e1d6c 2 -/usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/ei_connect.html c168689777cb8012e8260705a18a3e76101ef00cdd75ee5746508d37d7cf698f 2 -/usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/ei_global.html 7f8344d94cd4ad3bc0255b547d84bf15aa18f40a42887b9a4226abedc1dbe58b 2 -/usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/ei_users_guide.html f1dc69055b8c5f9d0d0a0af0c9dec5b3bff613d2c7dfa6dcd46db6ccaa00b4c2 2 -/usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_call_cmd.html c5c81fa499096f18ccd305cf944fa0f9a4defefe297607b0459a04705df25594 2 -/usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_interface.epub ae1754dc1d486c5d8279965cb7bd518cb1a2d87dd4d3597d11729cad9f1e9f71 2 +/usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/ei.html 756aee2d12fe23ea8197b6e6aae96174e9323b7e3f1fc134577543a180979332 2 +/usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/ei_connect.html 7de3634592c3ff65e29dc6fb6e400215a277c245d5e8d0404d1c3ecd82a2261d 2 +/usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/ei_global.html 27242bb6ae46d394d64bfe3a92087907394ea9797dfb3839cb0e9882056f0f3d 2 +/usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/ei_users_guide.html c4e53217252ff12e0cfe01e409d12aee2aa84c55baf57e5c6d063e7414b6ef6d 2 +/usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_call_cmd.html 837a63314247afefebb201b998ffc8efa6272eb6a49b55bcc84ee0ba8231e93e 2 +/usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_interface.epub 7dec27069e0440b6b24410781fc45ef755da2bd931d46999da5c1c330e052e2c 2 @@ -3007 +3007 @@ -/usr/share/doc/packages/erlang-doc/lib/et-1.7.3/doc/html/et.epub e88165a3b22a5c28a42a653c435795187338b05d65a95de8317e622a6885286e 2 +/usr/share/doc/packages/erlang-doc/lib/et-1.7.3/doc/html/et.epub 556ee4e07e66faf6a0793342fcc2b9bde349bea4de62b14a7dc4d34743d632bc 2 @@ -3010,2 +3010,2 @@ -/usr/share/doc/packages/erlang-doc/lib/et-1.7.3/doc/html/et_desc.html 491b7a56898204d68a80cfc5b70ce252139c1d01e461f55b521dd94a8c678a86 2 -/usr/share/doc/packages/erlang-doc/lib/et-1.7.3/doc/html/et_examples.html 35d371b7c620ffd8372db29e41247f3f675f3a15129f4b6e1352285b5c3fd9b1 2 +/usr/share/doc/packages/erlang-doc/lib/et-1.7.3/doc/html/et_desc.html 94b9f7e6e79a7921fe13efb85115c1b2815396d4847e62742db3e821cd31a4cb 2 +/usr/share/doc/packages/erlang-doc/lib/et-1.7.3/doc/html/et_examples.html d0810a704e5d453d4d2f1c064b50c06eca98b74c2e8b15ad7269014a64c5c360 2 @@ -3014 +3014 @@ -/usr/share/doc/packages/erlang-doc/lib/et-1.7.3/doc/html/et_tutorial.html 45233b6290afa926886971a9a070fa9d3696fa3a7b76d0db7f8dbec951d4f7ed 2 +/usr/share/doc/packages/erlang-doc/lib/et-1.7.3/doc/html/et_tutorial.html 54af4063363392ba6da9d692ad65f66f2c914f663a361cbe95822b276c4dcbfe 2 @@ -3040 +3040 @@ -/usr/share/doc/packages/erlang-doc/lib/eunit-2.10.3/doc/html/eunit.epub 4fbb226eb291071e66fb4ea7539dbd95e3e63de56cb3db44afbcfae71434084b 2 +/usr/share/doc/packages/erlang-doc/lib/eunit-2.10.3/doc/html/eunit.epub 68e1cfe49319067e4329e7f861a36b67f85d353ac3b5ca2f5f3fca9d049a2aa9 2 @@ -3044 +3044 @@ -/usr/share/doc/packages/erlang-doc/lib/eunit-2.10.3/doc/html/notes.html 95352aef007027a5131e5ccd243f8fd1813e46fb571685cd9d6ef19f527b148a 2 +/usr/share/doc/packages/erlang-doc/lib/eunit-2.10.3/doc/html/notes.html 2895064a45e15bcd6693f5c9b341f1a4cd51541d8c69337c27c164860e6f79d8 2 @@ -3063 +3063 @@ -/usr/share/doc/packages/erlang-doc/lib/ftp-1.2.4.1/doc/html/ftp.epub 003aa63de91e9025247f4ef687bd5da2156efe781c072d616565de44297e049c 2 +/usr/share/doc/packages/erlang-doc/lib/ftp-1.2.4.1/doc/html/ftp.epub f4601bc10fa30dd5360a565d34b524e347806801c8996f1a561eb5d4144dce1d 2 @@ -3065 +3065 @@ -/usr/share/doc/packages/erlang-doc/lib/ftp-1.2.4.1/doc/html/ftp_client.html 73685eec283a9ecdd7ca0252dd69546086e210ecc1870d5197adb99f3d58cc1c 2 +/usr/share/doc/packages/erlang-doc/lib/ftp-1.2.4.1/doc/html/ftp_client.html 4e25b8969807b423f18f0f2932fb696a82a20f76d033828acf9e0158abb20585 2 @@ -3217,2 +3217,2 @@ -/usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/http_client.html 2a55ab0f4f73307e5ae942c4f47d711a577ec74c8b55ebdc52183fa255448353 2 -/usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/http_server.html 936bc249508ded533708fb39daa8aa79a31fbc02462c25ea573b0bdeae7b1a1a 2 +/usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/http_client.html 42d5dba3b1476c1673197e2049824be164223a4bd9635f0de32a4445eef7df1e 2 +/usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/http_server.html 10bb39e405196d40c56d79e9d44102d41cd931fb8a09cfc2053eb416b8413023 2 @@ -3220,2 +3220,2 @@ -/usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/httpc.html bb1ced98b8fa1033022a25b1bc11b168384ad7d0a16a2bedec55218a8b0a0fb2 2 -/usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/httpd.html cf2a6be4e9cf4592bd7321fce2ca1cf438db79896cde0b6230836ae85f86e116 2 +/usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/httpc.html 1b8d23c310aeda50470b58619005f0e5601e92e3f8846837f6cbf249bb505315 2 +/usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/httpd.html 7b490515c64ab961fe3e37377694c9f842c1226bf0b96dc89476580941712f8e 2 @@ -3226 +3226 @@ -/usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub 9bece6fc1a11293c2cddcd701340fceed53ec162059a1fa4ff66052f91d93f5b 2 +/usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub efd1b8a4430de3c443b0c8c4d10f3b4564131665457e306dd0ffc0a152dba0f3 2 @@ -3228 +3228 @@ -/usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets_services.html 5d002a7a76fe2b1c07029475ba57bb8161373d483f750de42ffdf738f31b587e 2 +/usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets_services.html 3d2dad7bb34403178044fcca5bd7318b0bae4ecc975c13d7697da1b8929bce7c 2 @@ -3242,2 +3242,2 @@ -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/allclasses-index.html d9f9e98e05e68af431c61d1e37ac713980529ee0da59d6fbe30b1aa547ab9f26 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/allpackages-index.html d0c1bf9100d85eb545708375cbb158a5e538005edd787169573a2454be20a5ac 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/allclasses-index.html 5816af42caadbecbff0e45271ca46408b8e30173773e013ae1653b86549729ec 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/allpackages-index.html 565ddeb0849ff90c505321e2d34ad3365d8d8d676d331143a3d7a7b0a7c12e1e 2 @@ -3248,61 +3248,61 @@ -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/AbstractConnection.html fcf4f6211d450ec609695c1525b1c6659ccaa0cdb9f440e00df81e481f33cd18 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/AbstractNode.html 5c7a8060a0752f4bad2aff5c55305202438690c40eb7cae7ffe0fb0ae42d2af3 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/GenericQueue.html 2043ca24d76b28f78c063f4b25a57784c903663de116c2696615aed42e6eca64 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpAuthException.html 6426779573c675ba7b9f95f0718ccef66e202f347db403c84361bc0c656d08b0 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpConnection.html 7686a49ee1cf731b68d83202a587b9b53952099cb7097f4b39a3075fe60cf1d1 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpCookedConnection.html cab67fddba8e39a19d04e3fdd39bf0e21927a4d4a7aef3b019c00edc460a53e1 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpEpmd.html e1492dfd67676833f14ebdcaf56cd66ce27e489dcc8013300b14215ab5383fe2 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangAtom.html d72b3c9abca433992f8db589b449cfe88d7f781903c8e8f253dc275c4eca3359 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBinary.html 35ee64623e7f2f15119188d7b1e4ef3d08f67183ed2682dab35b957d9f4240f2 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBitstr.html 84029d39cb0d92c42539473bc3b76e6faec8f49611d82ffd5dda8ff7571801c4 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBoolean.html 16e135d89de7e0428e942fd1dac07423052d42d835fd556db9285595a87fb52d 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangByte.html b40d7bba17acb268a951968604493adedfd64ba22494de0fa6f4e8fd39b377b6 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangChar.html f5f3c30e304c712391a1a7efd9709a39ed1352b202de6cf65a9bddf1fea5ad25 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangDecodeException.html 4d2b3e1401d62a56dcc5997dc584e45db7892e487b941abacb268b9623519a99 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangDouble.html 30a461220edc2ca5788cf0c77e749fbc321bc50cec502512b95814df1a6226b6 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangException.html 9763bd611ac7cb4f39f8983afb932e00e1d9ba4fd3d15a31aca5b7ce61e9ed73 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangExit.html c374bbd8508860384802d89cf9ef89e3fff1a88e4d9d3e4d700b7abc8170fd5b 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangExternalFun.html 1032b0bb502752348a2d9d3c2f4eabc167ab63028b9dae6c5735c27caf4b1f84 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangFloat.html 81f9a23514cdd6fc436f7dea2baf8c03c6dc6fedbcd4aad07d13f9a84e441757 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangFun.html 2fcc7b34ddc87b0cfb4282733c3664b19267a65f4f34f997e3ed0bf9778518c6 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangInt.html 211c92938bdf878dacd6906cd0fcffbdd49ab823b57eb8a7be15a9908bcb43e3 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangList.SubList.html defcf6d8f1cdab86f4b16ca117317dc0f18bddf4e92e2e5a9405fae47318f1b0 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangList.html 8048dcf0b7f0ecaf45739feab8d66d556d751c2c25ab50e5a6dda1af78298f30 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangLong.html 54f3e4e480b644aca50649b2c30415e9a34a92297ae6f3f27164cc02544909af 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangMap.html 982a92e3d86cee2ee69223bb7b8b7dcedff33837dca1da1b4d961fc381861cdb 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangObject.Hash.html c8cd537177fb963c937adc56034a2d9d0107153b81fed107d2a096ef9d4f41e8 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangObject.html 6bd4d16ccc5ac118685f35763b475f6bcf42ccfcd5d45044d01c355896f60409 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangPid.html 5896f943c2d0552a1113b07c7c71106a6d87225743f2137b8a3f3616d691c492 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangPort.html e88ea49d128bf247c0f94d0fe74b635af0ce41e5b81e010329808e88672e58cf 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangRangeException.html cc7b235d6800ba675b8a7689421ab4bdd0af26a327f306be0032a617b1cd0f47 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangRef.html 798ba140754ba842150aa7aeb9de94840cce2b984931ed2907c447d570890c22 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangShort.html 6346eb829a2f0aca7af58dd6cbbd1b3e200557f02a84dd792183184895192bb5 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangString.html a1e64770e6f61b67c1202bfebe4cd0607b9e10cabe51ddfbdeaa921476d092b1 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangTuple.html 1cbc8076f9fb46470b147549d34c14a42f1b12c4ba3e837ec1b9dafc039dd386 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangUInt.html 2fdb9b37565dfacbcd0f204e1289762fcbdec1bbeec4017cbd17bb4454f05802 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangUShort.html 526fd5d8344d023eecd78b313a9175b01f0f25bde71e5ce0c76f0b0de7a9a4e7 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpException.html f4ea9acff4e75ee206ec40fc4b5eaa2223446ba2cb571204e6e6a2c75ba1a096 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpExternal.html fc69e3290c34ffc6e58c19c250a6a7a4acf131b9c9f00b305d05886cfecf1810 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpGenericTransportFactory.html 48f0c23e4baada881d777f88d696462458c7b6fd16ac235cf7932dfe18de5f20 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpInputStream.html 62823f70b2bfacc1eb73d80099fc5ea441ebe04d0dd093fbea4c3ceb954bfc1d 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpLocalNode.html 1ca709b1e9b6b11d362013ab099c30534060ec4a0dc90e59f03e18320766ea1a 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpMbox.html 827c86ff06dfd8d93862f3fd20a71221b73406ec2d8fae8aba02fb9a02294ad0 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpMsg.html 8f49690c9a4490346f13a11ece17c1d81e42920219e5927c80d2d2a34665272f 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.Acceptor.html 12a9c3556771d4faf9d92efeaeca82d31525e72698f48cf580db16aaa6a23be4 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.Mailboxes.html cf001ce143ae477db3bb0cae60198d1283fc49d4477c6a3aa4696aac65e81923 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.html 2d58fba981cb9812a904f4bcab6cc4ea0458fc777b16cc5d4bc18cd657e5b325 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpNodeStatus.html c20db8e6e0c91747eb1db54d2bec15bf18bb0f889306a546724c48865ae037e7 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpOutputStream.html d298bcb01d355edbb988d18e5c1adb83945c39ee8bc758c128c8e4d3d3cb7c3b 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpPeer.html 80f22a55f83f20e0c4ed820c62f4d028a494ea886275283e8a4c660e88422396 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpSelf.html 5fa0d95db614f7a944f638e939947e1204cedece09afd43c3596148ea151a023 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpServer.html 05bcc7077c2fc8affef556acee98500df8a5dca6b7f9c1664cd5ac41e8913ecb 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpServerSocketTransport.html cb0fd02982c94f25f31d71ed81aa83838e25f3590be2678de1999446e53e84d2 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpServerTransport.html 57d426fe018b5a4d59d8884f4fe0bdf847994beaba02e1623e946e262b6f7a23 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpSocketTransport.html b49b107ee57c49296eac1fffab2e7ca536d7fc739ffe1677cac33554d5406c52 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpSocketTransportFactory.html 468a7b5049456a1e4196817a0e55ad334a8fe008c44d9df6732862fab0c3fc52 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpTransport.html 24a70d87618c04a229ac57a6863a79d8e2ba9dc8d7d9e2335446873185f0ae93 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpTransportFactory.html d2296f53af9c54935c7902fe223e7650713a5ae2085764d1889524012972417a 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/package-summary.html 2b39ef98974187afb7acac1e8f002c6125820742ddc77fdb291a12edb0e77ed8 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/package-tree.html 61fb1b6edc1e09d77d80afc745360298f36ff04150a07c0329edf9ef114bcb3b 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/constant-values.html 76552f505794c1ce5be5df82eae3c1f51501dd7308f2ff07a54616a15972773f 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/deprecated-list.html 8d486b7f99a409fd5f6963f1eb6d0b137a28740e9626113ffb5904dbc8df9707 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/AbstractConnection.html 4a1a989b977360c8c8ef0df755e3f3850882e12b9964b594307edf55eb09dfc4 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/AbstractNode.html 6b8a899c53e74a3d38beb7fdb69e1aac6c1aefbe3fdb08111460f8e25f8d82d0 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/GenericQueue.html 8aaa948b33172d8e391a34895774aaa25966a62215ff491009caaf107afe92ad 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpAuthException.html c80437f4351bdeec56b61afa662687359214d5f013cd259e5814bc5132246767 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpConnection.html 307c43e7b3edef30b1b146366fa52cbf254dc00c6d7300fc3c884da1bdd67cb1 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpCookedConnection.html ee8d8b27cda3385d2cac7ef860781e0faa2ecdd32c7261a2ce6fca4412056e32 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpEpmd.html 26153463c3ec6040a717010a8ca3b4d272c7a654b58e1a269eed54d4487e7c0c 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangAtom.html 5694f4315834b3b88aced5b8ed165d7ee2eb1c380f495c747adcf8136ca71cc8 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBinary.html 0fc7cbfeb6140857e7c9249649139192d66854691c47baa5d9d4697d82e528a1 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBitstr.html 6e1b7d523b4937fcf958dac64c10c02e256bf7663c7d0e2f8745a3ebc8c94de9 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangBoolean.html 09839172ee58b816026d7f451d1e691238b1782eb29d395a935355ea39c04da4 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangByte.html 7dc7654ab1c90fe70a910ce956803833c7b6b982c288c469facc659b5a15aa8a 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangChar.html b29d25a8517ffab19ff860ade128015d4ae87f95e057d35f2a21773e3c35f267 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangDecodeException.html 3c6a5fb956d5799d47d0138d87fe0027893e7c21290cec74074adcdf2611b638 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangDouble.html e2063a0598f048e47dbfa08967f97b200dc45e38046b9a9012fbe666d31a1f97 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangException.html 40f700d78bac911cb90abe2663b55bc945ab09d2ceb7beed52edc315276efa62 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangExit.html 8e46715b20c8f636eaad70d29dee11bd7ee9995022be5bc1bad018b5785454ed 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangExternalFun.html 2f557a4df9f515dc35195a85deb7e0b1cf3abafbb5ac9f5a98528685a74af753 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangFloat.html 0140ca42725673a68f3afc74b995d530d6538b9e05ca0bfa45facf036bd774a7 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangFun.html c29aeaabd9a38bff5e35ace7e678c8bce90c6be9581a8782b81a89f5319ee320 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangInt.html 8a923db522ae487dc3f1e198fe5578f2e8761f1d28be030111e8dfa6e2417e40 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangList.SubList.html e641d3af689d45c35564d95eec00d48bcc2e318faf9e668de16bfff51fb1d482 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangList.html 44af451133c4cd0bc1680d3073f5c64bc827aaddb5aaa1eb4a8f540b29d551b4 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangLong.html feabe7632c491de94a0e321c06cd6d8d8f94978d3cf33af1ba3d71296a2a280c 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangMap.html 39abc7ec93251dc17260d1c4ce37973487e54552f583c09ec20816476897a7bb 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangObject.Hash.html 8d7cca8993c42b5161aee9d06ebecf1bb55f0a55b7a612ecfa1c470f6daebf45 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangObject.html 0357114d5da11d76bb2f0d13774a5920d32954d1e5a1808de4528907075ebdf3 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangPid.html 555b09380a6afa78de6b1b28e522ccf15c54181c0d00e653e2ae3f7c01fbab3e 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangPort.html b080fb234efdaba732463685f949692827048617457c2887b36a603affa56e68 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangRangeException.html 1bffc643f51dad46a4f0f3376cd7589f1b7c1b24460a38084ef91021322d2926 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangRef.html b0e5957e487ee9e1fc4c990b4f7c4f69ecbcc81d9405ff853a2106bb53aa8112 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangShort.html 4fdb35d0a13e627444dd374110a69534a9a0c0ca367f841ecc6e3ad968131e83 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangString.html 95d79f98d49e34a691e83bd775b82afd1104e739c6f1c62ea2409de7a9313b6e 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangTuple.html b837446f15a5043d18feeed716e03f7340469db42737c8a73a7f9d62a2bb91c8 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangUInt.html 1910c79d3e5d728b36257488c2dcbd17e1e04d979d8ea0c6be7ec9e33e543980 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpErlangUShort.html 4b524226804489315ec1bdfddba544f6ea3b07782f583f328daa63d717e049d9 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpException.html a0a214ee17ae2115ba7698714befb8920e21d173492a2929c6c36e14ad037109 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpExternal.html f80b6497a8a9cbf9a1817007f98853d546c4f4e7e63fc9e4ffe7cb0d606e451b 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpGenericTransportFactory.html f49f2f997f7a419f3d1856a4ceff04ac61051fe5a7313d02c741541afbf7200e 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpInputStream.html d23870889d48d8994b0df03752fe1f61ed374e52ee32d476e9f28d831e32e515 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpLocalNode.html 4806310b31966fe50b6a0152740225b8f24482f46b4b9413744c64fb298d33b6 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpMbox.html 7ee9e3209bff5c0fc7c62ff519f0eb3d9079f01bccc655572fc22f73021cc3c8 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpMsg.html b51ec8e0532c29387fb34155f64cbc0cacdd8ba69edaa03a09bf78e4a49b9599 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.Acceptor.html 25ce1ff13ec0baeed107836187f090b89e284d5d0ddfdbd17fa82b295e86a994 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.Mailboxes.html b95d8221dad062a4836b03029dd61996359fba4f2d685394ab440783323526c2 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpNode.html 37110bfa9397c75a5f0614b307858bfab5f5ce8204646e488a67f2f777c46ea6 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpNodeStatus.html 8617aea4ff93e9152205d9f6f83c9ab91f4c46cab6b4cb645ad20711ecf8823d 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpOutputStream.html 8565eeadfe9edc275d2e2de66d4ffb499fe9834718b5151a4f888ecead2e1ff2 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpPeer.html d6e7f8bca2fceb4e5e0e3c5d03e229afe07bab6cb1255ae5b496438316ed3d0e 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpSelf.html 6c893d7fe5f629579c994c428367db1272f0e49bbcbe58def5f349090efcab13 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpServer.html f2d7acb310838c2a88b3f557f19409fa508e578b2dc5abdca474cf6a4c5da474 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpServerSocketTransport.html 0b9b2ff2de24332e98458a98ec0c18a137ff6ca755a5002a7b46417023c59138 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpServerTransport.html e907e5497dddfaa3d5f4142708ba9eda63953c080524bbadea693929c16c5df3 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpSocketTransport.html dcc31733357d427ec9ee8a24dfcb63323ce06b54e70237a9f688aea6b95a8f8f 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpSocketTransportFactory.html ce15b61cc3a97f34c185243901b11fc010e696a02bcbfe15f0abe62564ffbdae 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpTransport.html 404ba8519986e136a646ff7a4a7eee7e6b57f7420b8d10247c98dea40c79bd1c 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/OtpTransportFactory.html 4ff23a65b11dbe10128f978f984187bd4aa96a4ba08371f2fa38d165d41c1311 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/package-summary.html c01f75e17fed31fe620429d4e30f49dac5282b226cdf2b499058f1f2bc715911 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/com/ericsson/otp/erlang/package-tree.html a2f95061f08cac31ae0be158ccdc60058a0f5c707a952f69bc020f2f2865228e 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/constant-values.html 9b514da1a8c9c464852666a1ecb4ec38422a4d10f69d13dc82e35d91aa3ff8fa 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/deprecated-list.html 9abb97588d4e296f13ab44b4bb5f837a4325529facd6890bd0a777b7fe65be64 2 @@ -3310,3 +3310,3 @@ -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/help-doc.html 3df7d3308e3bef876aa84b611c55ae5f570e85ff3ac1ed98088641b4253942c4 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/index-all.html 2c9c74d537a70bbc1d6818a371a14db36c16a4eea5a67bf1b16f52722c0760a6 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/index.html f8e1c0567793ab842419a3c44e78c047bc6d0d3d180f8404bcd5cf9b2727f926 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/help-doc.html 5aa2f52c4c83850db0cc7cbb525e7ee031587da3b53a1e7c49e83574095c3abe 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/index-all.html 5ccac2e52568e32ad4c99d030fd14e783cb76a790bdc9dda7f10ebddc9e343e1 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/index.html 9f4d6f0e2bb17ba5aea670efd947b1d06d909ff80fe6cf3cf170d018588c3197 2 @@ -3322 +3322 @@ -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/overview-tree.html a48c954ff3ee72dc041545689331bc8118fe8efd64a56e5007864beac71b6c03 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/overview-tree.html 1ec225cca77734c5ed1fd2b6ce9187d49a755c9a10e72bfa6bd534be3ba01fd9 2 @@ -3365,2 +3365,2 @@ -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/search.html e00b22e74f05b3375933c824a27ba13a200b8f7f1f80dcf25703b9d0bae7384a 2 -/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/serialized-form.html 7c23f7984d08b1e4b0de8a4026bab3f067eda12640c1d90dfbdf4f461d8ef98f 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/search.html 5223d18a684e9027f3ade8a158eaed35b322a07e3a8984d158bba65324f8ca50 2 +/usr/share/doc/packages/erlang-doc/lib/jinterface-1.15/doc/html/assets/java/serialized-form.html c3d25b1f6a3705c5f72e8e5877a2134036a6f48ec45aad0d11e4a7c834f9f3db 2 @@ -3412,2 +3412,2 @@ -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/app.html 1183f079dce10961c5c900856ce84307dbbce601afad193aea9de314681f1322 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/application.html 7bb7660b914d92753364212c6e4a5af91fc267ed9bc92df0a8865c2f7c3358d7 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/app.html ad22cc979fac5b8647f8c1badf1414781f3b021c53887f6e98cc039d38848dd5 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/application.html c55bcef553f1a9679be1ec2f43431a52eb92e0dd293516a43b29b58bced62951 2 @@ -3417,2 +3417,2 @@ -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/code.html 5d3af475f577f63065536848f61697e43b06d2dae3319b5f5197b3512750df88 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/config.html 81abd6070ca5fe72ad58b68483479312740ef53b39af44daca154dff59b60306 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/code.html d0c3929b6394ac8159cf0ce101b65bcbd42ea8a4ee1b5f9533548b5e6b4d7543 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/config.html 97ca9d8c0d563c24fe5acfb52b530bcdb7689a6a47fe0af09cdba7496dbfc1a6 2 @@ -3430 +3430 @@ -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/eep48_chapter.html 813c006d5ba813350de6dc12d11acc8503bfdb73784d33ce4318040ef9044451 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/eep48_chapter.html 076feaac6c662a2e73dbe45d658e19ed4510fe790d70a1ee43de0a7cd69a74df 2 @@ -3434,2 +3434,2 @@ -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/erl_epmd.html e2ae5632cc97a4d9b6a0b7271b9469e91d5a9b1326b1c67adc71c70a969247c3 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/erpc.html 0a6ddcba8d3c37f6be368191b06bbe306b0570ca45bb1b13c11a4226a2a81013 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/erl_epmd.html 9effe2b6503d6fdfacf9722eeafb9588c0d319f1cfd2e14b0be5048b7dcb8a55 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/erpc.html 678b01a2c172b7b06193a0a4726188895fb7bf216b30c4a3aaa8b3fb4c82ec4d 2 @@ -3438,4 +3438,4 @@ -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/file.html 225fa9f39a1682344ed0a0fa40abe124d42e4a24e01cf7d3f9f2d658dfa8b557 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/gen_sctp.html 4a418fa524713105500cc4748ccf75e4390ce81545ed8c32e6875c83768edf92 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/gen_tcp.html 3ba4da93cb1d0b098ee9d645363d2addb22eaf2fda87cd36d7794b56a3570138 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/gen_udp.html 135b4fc10ec5ab64dbffc5cc1762eb2d260e7514824ed16d61de9ee8bd7acc7b 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/file.html 8d26097ffb4b37099a023d3130917836a7cc672f84065300d3556b1ea6a06abc 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/gen_sctp.html 5bcef2955e996db0376d5b218307448443f82689316b82de5f9e6a962bbbdb10 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/gen_tcp.html 229d5c3cbe57b38148423dee086dd2c563732b239301d066fd6c515d6bd0c476 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/gen_udp.html 391f941e85504565fea0f83ce80a79deac52f10bafbdff71a0e628717472f933 2 @@ -3443 +3443 @@ -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/global_group.html 97dda9a638d9dd080317bae19191a946c0461932cf0224b15a3f7fed90cc7794 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/global_group.html e3cd8b7f13c0a318116b22052ae45299a007ea62e7da7b6adea3f67a3812cb0b 2 @@ -3446,2 +3446,2 @@ -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/inet.html 2916b06a76dabc583eff3ba1b6eefae6cf6d3edb3a420ad28866780ae9520b2b 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/inet_res.html 1c1390266e15d2321570d7bdcb4c9a38f966feb27020dbe56bc61434933d8b98 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/inet.html 6c31113574364866976804ed597eb4014b3d4c26ace39df0818ec665053032e4 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/inet_res.html 043df774f197624541f57a4643b9098737a3db67dee3655d398ba95102ed18d3 2 @@ -3449 +3449 @@ -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub c745b672b9447583d588383bc42722efb2a657b5778739554637b864a9e4c35f 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub 81e0bd5dd4e9ad97933b95f53c9fbef2695a4c86a6c7729758bc94c3cedb328b 2 @@ -3451,5 +3451,5 @@ -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger.html 6843bf200e5c75ffcefd9b4befa4c09cebf1808c15cfa8114a2202ada00d10fb 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_chapter.html 279c2f63c42ba872cf172ae5ed328ef27bda1c87349e3dacfdffb1024ff41a55 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_cookbook.html 52766d03fe057ba61b3716a210972a6d92ae8aafcdcef523f4b9a7f71a442b28 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_disk_log_h.html dc28d2d9c4b2de03b80bd573782f96758427bf1220c53c4d65a86d2b4c8d19b0 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_filters.html b2631a5f0e42b2f67f4e40e27a11c5c341d64589208a458a813c894207aa4762 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger.html d1c24a5e3d57d3bc3255c105e65178b0cc0a359c864654d93aa408b122965372 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_chapter.html 66fb4f08aad5e6e3178fd1077d08250c44fa25b4c0535686389273a3d5690d60 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_cookbook.html 002291fa3568f0d7118fa8e45d55b6e1d5a0b4b5c409e13a1b3fcf735cba2ea2 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_disk_log_h.html c387ced2e3f1160d10742ec6515144ff73a50af96d061c8b6ba8c715a964f4f7 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_filters.html 6bfe8917156e1d4c0bd94733eedda66c4d9f42f4875dfc46fdfe6a79f976512f 2 @@ -3458,8 +3458,8 @@ -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_std_h.html 07cb92a8578b5af3ca04c6c8ec5d8f9ceb35392445bee0d66bc282f4a7abc3ef 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net.html ee8fb34db27c8f8729930ba29ddd4f9aff416a99d473b95c9ef00e3e93315ae5 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net_adm.html ed7e02b6ec4330c94a00fde6eae8afd106a4f9dfe3d8871bd4dcca46cb338b7b 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net_kernel.html 91f19ef79223679df75dfc32c280c4f6b004bcae48d459b08510efe40421e77c 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/notes.html cd6eedc32c4bccda3ff0a83d779e461f6370a0186ad88734b74a6a285a269307 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/os.html e8d304fc62f2e81147021520822d37e388c25867dd031c2ffd3c9c763f6df904 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/pg.html 429c9807d2837a572b59fa7b59416eb7a68b0db86071f9d842892524e96af38c 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/rpc.html 949d009cf572582bbc93129dc5f4d6a195e0b74068c0a2539a790c6fe7c228a5 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_std_h.html 63201016a5bd0c868fb09fd4cb70d1c0b435b97093b72ddf0ac555911ef263d0 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net.html 9e8822c076dc9a819bed509fb8236a64b35bb7dc23e02e1b1966107369f4d86d 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net_adm.html e5f6ef199b2ba49ecb9cf1c15c0e736389a936ca3c26bbed7544e7147061a357 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net_kernel.html c18413b9a69f7f1335de51a7c5af6417134f11c22f767a52c79673368399f92c 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/notes.html a167bbaf4148f1cba81c2a231967aef414f721b67e4c258f207c0ff82dd9bc8d 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/os.html b6e78a796746e78b5ddff1865489098410a9c356345ff7cbbe3763bb9ed630ac 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/pg.html f7d9e840113d80fe79c8f525497866eeb5c15ae3fd392926ad2e2af89223497a 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/rpc.html abce4ba81f33f75c2d38b3b9d3f97bc34c5d3e2ad0126e74d77429f2f6cc02dd 2 @@ -3467,4 +3467,4 @@ -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/seq_trace.html aabbe3e8cc4f5e95db5aa465c20ac91f490f375693e1c609dc6a927d222b77fd 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/socket.html bd78a1e27c2921ddb80906391393e7968bb5499de9f7be2df17f8a765aadafe1 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/socket_usage.html cc55fa214c6a79fd1246bb49a3dd406aafc93a0f7b4f481774e981268b319304 2 -/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/trace.html b0ce456bc3e39c2042fc96f4243849de65db7e2a9922118858b20d69c50b526c 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/seq_trace.html c0c9fc781597094eae33cf7a7895b703b20358ef7a167a705e02329167963f2b 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/socket.html def8ab39656496a530d72c2b1c7f455c2e9b670f572cc8b505437f3276603499 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/socket_usage.html be62f1181c849f7fda3cc48bc62ddd7be995c92d53d057af7e175fbf7a23ee70 2 +/usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/trace.html fa610d8fad32b1cc04bc545af4a4449f2b4d2847127078a00035a64d567d9aef 2 @@ -3507,2 +3507,2 @@ -/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub 143ea230bc1598a455f09766507887267e9cf3b18489b4f6fc39acc9c856ca80 2 -/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.html b50aeabab34865752cec6868c4b7996f4f4dba37c26313484f2e76f1070463eb 2 +/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub 41e4f082631a26e7b574c3ffe52cc0faa2ac9b2fb8c7a67df20b432bcdc49058 2 +/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.html d27f6eadcc7ea04515b5772f04e095d197fbd0d0794b8002b9ec1234b4793bd3 2 @@ -3514 +3514 @@ -/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_debug.html bb0d2794ae084e37b38d014062d9c647f2aa7b8a16e06ab3ace7a82fc963c89f 2 +/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_debug.html 74a0bd5650b454f0c172decdabcf22b6ec46395e9a1ea6ae1e4e9f221d1ba88a 2 @@ -3517 +3517 @@ -/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_encode.html 37141a735930e0e9a0cdb945e677912fd670f770fd032f45581895d5afa6de68 2 +/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_encode.html 38c873ccb52c70527a0edb4b15b192f179054fd14c15254a1a66a6b8623140ab 2 @@ -3519 +3519 @@ -/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_examples.html c80c859f5fbbc0a1a3ace0a367135452e97dedda5299657bcd9429853bedc260 2 +/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_examples.html 37cd2164267e268315d24782c487ee003996fd3077e1a28e7d9d42c0ad085319 2 @@ -3523 +3523 @@ -/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_performance.html 6eb568666346623736abd63e1fcd88d38ce39b0a0af650dd4749fa4fad01070a 2 +/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_performance.html 25f7817df86004efcc5d37b302f74d1ce35972de4f0af516b2c696c5b880d2af 2 @@ -3530 +3530 @@ -/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_user.html 48006bcab8e6184c48d25fa1a81ff4c9040c16630161f9d9788e1d1d559ee651 2 +/usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_user.html bce525d780580c65b349618563f79ab9e18c84aa91719143323f40542fdd9772 2 @@ -3576,5 +3576,5 @@ -/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub 96ebceee2b46feaaecb65aace058cc32199521d9da8a3331ea03314d221a6281 2 -/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.html 3d7549761c12d16da370db255047eae51e008147424e095be080811733814bef 2 -/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_a.html 434a945525963fa320064a01849e6a90e4a51fe1a15c35560108bacc585297f8 2 -/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_b.html b39a6a833008fc0c6638a7599a08eea3e62f1d930425e9022870941079a0c684 2 -/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_c.html af827aa94b2ebb9a6d53cb88b0ded021750f13982153243ffb1be7dfe8f1a36c 2 +/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub 3bbdcab30f8ad5662625da372818c0434ae98f4aa730cd74882ccc5ae9ed25b6 2 +/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.html c2b994752c4dacd691f970cf656f13f0a8a53f46815b0cfd111203b1c32eccb6 2 +/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_a.html e14de09247ebc67d09f7698795701efdaa70c5d0c0ad4a917920efc1cd046e58 2 +/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_b.html 611ddc7eb823a784be7d3b1801b7517f8087d93dc42505ed89612fd706f8320a 2 +/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_c.html 541409c461b483d0602587660189e350fd8513d8a616f2e8f638a335a2eb3ad0 2 @@ -3582,5 +3582,5 @@ -/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap2.html 0387f03f4d985142c8eb8d3efaa37167a4a86e1333e350e6c8d53291667deb45 2 -/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap3.html fab223f46327d55436f4bd77d226313f0cf59a108b7cc7d722e3e60c9166b746 2 -/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap4.html c70fbc05bf4407c3570b7f813e7d1c19a4bb0c165dbac2cc942a4f3c63bb53be 2 -/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap5.html eb0973d2d37202072f4dd046523568978410debd01709c88f2f79046034a08f2 2 -/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap7.html 9c1e498e8cf528ce4ba917a5f2139d925553ef6e1b85bd182da6330d7bd6413c 2 +/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap2.html b1117c77c22b4ea2b2323e1800e6592b1b1f91da658ec0e4d1035b9f9ff9019d 2 +/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap3.html 8377f5ac916e1bbfe0f45e85512391d176adf870b1ad4049d2cdbc59dd25a644 2 +/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap4.html 07c47d7b758b7ee453728f1dec5fd09e175c7181b96d7ee747ac0b35df96347d 2 +/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap5.html dc382844ad882ee7cba076879ae843db9d688c7901f52f24209b2b47e783db4d 2 +/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap7.html 9466782101041c7df2b7b8767a063492c57777f901219b23f6a090d4b222c1e1 2 @@ -3590,2 +3590,2 @@ -/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_registry.html d766e041c6639c573e9158e47bdf9bcb3d8fe70b156030cfa791bc4fded107ee 2 -/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/notes.html 21a3bce8c9c24c84d44778c653142919e6ebfad29a72b2395bde2dabba4370e0 2 +/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_registry.html aad5ab39f1b926b84fb888e6e35ab3974854f969ebf39b8b8b5eb19e03a05c4f 2 +/usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/notes.html 2acaaddc2c112a87d007da78d8dba955a2790c4a138de01f78769716177b2a97 2 @@ -3622 +3622 @@ -/usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/observer.epub b01737c388bff2e975d8f5f27f96b2ca22c60ccc9fb1929638e05e8058cfc1ca 2 +/usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/observer.epub 98c975c57fbfa4aa67fc7683332259d8c4558712678c704816a6ec83d3e3cf44 2 @@ -3627,2 +3627,2 @@ -/usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/ttb.html 30d42c03f9495cd3ef62e3197054dadcb7e870de18509f828c9239b2a58ea731 2 -/usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/ttb_ug.html 86d0773f90c19da7f0f151277efed61c4aba4c12f5fc0664e30e3679b7e2884a 2 +/usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/ttb.html 53da38d91494313f897586b7e9b89ecdad680e366efd750451d4251c0a8ad933 2 +/usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/ttb_ug.html 5068d3de41c2b14e4165a285616a59ac00845f045c303dbe33a0ca283641c710 2 @@ -3649 +3649 @@ -/usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/getting_started.html 4e8f8784533f2528c94d35f5b2d9b14a4fdb1d5a13dba28b907626d2a5a6ea1f 2 +/usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/getting_started.html 03ce4ac92ddc2d93d481830852e7d307b53fd789e4dc1eeaa8696add032257de 2 @@ -3653 +3653 @@ -/usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/odbc.epub 1f2363176eccde1e4ed1601109c85accb362d64d010768534c241b8b7b925881 2 +/usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/odbc.epub 7e1ace19cca1015d5ea7553367c4d7af94387717899c63c32c7dce8145ad7586 2 @@ -3679 +3679 @@ -/usr/share/doc/packages/erlang-doc/lib/os_mon-2.11.2/doc/html/os_mon.epub 3a2a85ded720ed1bcbb9ace02715b0912d50b24fca3797c31ca3b5a5a8fdf196 2 +/usr/share/doc/packages/erlang-doc/lib/os_mon-2.11.2/doc/html/os_mon.epub f266c94672b52589d16bf064243d8e109d0f5927fdb32350696157ca219c2be4 2 @@ -3701,3 +3701,3 @@ -/usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/leex.html b6a6be8243b3fbf503f5b8040698564894d91edb30dcb172b27c36fd0d264e54 2 -/usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/notes.html bc62d45e3fb639fbfa58ee63ecd71e7e5c1dbe843442af50789502fc94646a36 2 -/usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub d83d76b6cb7922bb32ca4c55c53209e2c5f54645981c7370080dec743214f8d9 2 +/usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/leex.html 9f9629afe11b2ae3a09e75c8177aa221697d64e4d594f541c6aa5a4ea78518d0 2 +/usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/notes.html e84fee985e5984eaf6d54671dc10ca8835a5c1d43f861cfcdf24873ea10378a0 2 +/usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub 375c5a8e5436f32efbd514f1b2b3dc0badc7e85d99b25937200b91afaa84cb16 2 @@ -3705 +3705 @@ -/usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/yecc.html 36bc595bd426891ff578fdb8794e36cd208aabb5f86d29c53e04846617f987f2 2 +/usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/yecc.html c93f63c36f69952e8b8a574a3d1fcafd9f1cf76c3456f4a903629c40a1d19cc1 2 @@ -3725,2 +3725,2 @@ -/usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub e75eef70e3abf908799a54fe5457411cc3b03f51138b977c5ff9476f170a2c81 2 -/usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.html 231c20c60037ae32178990c512692e0867977676c0efb3cabdceb81c14b5f7f5 2 +/usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub b5de9095d58c504853c76c4d697f12b8412096946fc4acfe325bccd07e227c3f 2 +/usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.html ea6e84c260c6744a74de820d3572c67a226964785b0e8cfeb135debbe7e77789 2 @@ -3728 +3728 @@ -/usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key_records.html f66be59fa2856cb7bda6bd59037e28850eb77815bf0f02abaa7bb331e975be68 2 +/usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key_records.html e4cb9af9c9b84f02293ad0e1913274386b745360a86c313b0f24a794cb76a793 2 @@ -3730 +3730 @@ -/usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/using_public_key.html 9f29da1f7e3bafab78e08f76338779c673389218eb7ad1e1677460cf8384dfd2 2 +/usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/using_public_key.html 085689bec03bf0b290983f67c89ce9647bc620d85fdcfbff224d49459d48db94 2 @@ -3753 +3753 @@ -/usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool.epub a8dfe8b5af406b1563a58f55733166cfc090423c0e03729131d82cbe27a58ea3 2 +/usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool.epub 526f9ec0e8e56bb63a23b2302f7d7b9e13900b3c404e69bab18fd82c7739c1b6 2 @@ -3755 +3755 @@ -/usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool_examples.html cab3ba8a07563ec2126244d019a4f229913fbe90490bea9adccaa8c11d16cc17 2 +/usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool_examples.html d65970112e14349c2815925abf14e13607bf47a1bd7714abdb063bcdcc111a8e 2 @@ -3789,2 +3789,2 @@ -/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dbg.html 2cdf45f9bd292648f5743e0b401ba08b324f826b3533e6d490303e315e45f804 2 -/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dbg_guide.html 405f9fc5086a895c12fe1d73ca458c8c56c1d89516a1b16b915b407160965d0b 2 +/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dbg.html 252ea0f2a21278487997fe4a5ea5ae8dc44694f2922b1ef3c048cf67284f1ee2 2 +/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dbg_guide.html 5750d898a33a751ba72294cd8a2490602d57348afce9c0770e7165c74ba90506 2 @@ -3802 +3802 @@ -/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dyntrace.html 70a3ba83308b8cc9c02d4f491e0b7a020c94f4787d4dee7b2820a9e1cc06291e 2 +/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dyntrace.html dfe2f36103f7d7cd711e29df876914e61a4f99ecdbf74e62c4f20c9cf2bc041f 2 @@ -3804,5 +3804,5 @@ -/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/instrument.html b33c192d6dedd5275d0e06463169a8676394a79ed8a404787e33fd7aa67a0e12 2 -/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/lttng.html d80f3b0b994855686cfc345c96190ec544c64baaccdaf3edb615bb2408351628 2 -/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/msacc.html 1c57b02028c42b7f4df92299ef104cfd8d7e704aa5ec0610625dc4a1dc427236 2 -/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/notes.html 9a8f33d5035fe5237360a83304a4f2752cfdffe77e8af2abed1398de17e9d65d 2 -/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub 98bd3094a90cde8d7b44babe3e9f44d93994ee9ab68ba7f98d18c9d20a34536a 2 +/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/instrument.html dff140102bedf0d3d5c64160f7e36e42f73eb9b160b37bd8795350e674fea42a 2 +/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/lttng.html 897d16dd4bf6ee46861bfa09a7339f8c6ef5720fb13011c468837c50d05aa437 2 +/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/msacc.html 8904ffbf0b1b356434b2d28bfd8b3d31e942726cc4d726fb05e2ef96c8c89d95 2 +/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/notes.html 62a56ddee9e7570e35dfe9ce204047eaca5339c1c3488a1ad5736506134bf016 2 +/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub d5789e0024d74390300f45b4101b9f4604428cbeba5942b0a5d079a871323590 2 @@ -3810 +3810 @@ -/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/scheduler.html 61a11e5f8f56ef3d45bc361c53640e4b299a1bc352981d878f0e822e5dfb2e4b 2 +/usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/scheduler.html dede56542127ef990a4a78118df35ff9adcaa25cc161881db44aa3b4d1d44596 2 @@ -3826 +3826 @@ -/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/appup.html 07bbff19c1f755c1cfd3e7cd3034958b8fb8ef7fef1cf5cf33f4205bef00bc02 2 +/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/appup.html 6ea524d41819a85b1930bb12688042e3882ee32d9a06084a204235c531e6f8c8 2 @@ -3839 +3839 @@ -/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/error_logging.html 58387a4e79b3bfaf981f72581c57c9c695d1ceb3191cf9b1e9b19308234456af 2 +/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/error_logging.html 93dd20026022118fd17cfe4ad7fa3d0ee5ca90d1e4bb1b61754c5e07e431db14 2 @@ -3843,4 +3843,4 @@ -/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/rel.html 5d755fb3c80ac7e438d576d3255e4e301e9faca6cafd1767659790bd9acbe0cd 2 -/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/release_handler.html e32616856002c6d8a62b973904b3e97ffa1c5cc48452afd40cff2896fe6c7f17 2 -/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/relup.html eff8446cc9b50c5a07a0f2b1fffa54b72813e509eb7251d3cde4136d5af37486 2 -/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub cf06829696b5a76085e738c0d4dcd089b59b94215bb01ff63565c5bf31042dae 2 +/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/rel.html baf2bab4ef21c170ece2eb83784b2f934f99dfa786b068abb2fbb73bb6a43c3e 2 +/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/release_handler.html 8d2e6933ce66486a074cdb818a6c5e2924f27f3c8d0de3a4682b616b8167b5ba 2 +/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/relup.html 0dae940aef826abeca7f143d775e057167a85910a918f850061dd8406723c8f2 2 +/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub 00813450feae2325f738b773d46fb51c79bc73458f2e7bfc5ccfbc95c8afc5f9 2 @@ -3849 +3849 @@ -/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/script.html 9385f08141ef7fc2dc80b4a657baacb710fa454b746b26ee8ba51de69daec07a 2 +/usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/script.html a3d67cd9fb607228b7433c5b543a9eb6f038439b76a0ff30a7a74c2841a10a48 2 @@ -3902 +3902 @@ -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/notes.html 06099de595b11a07cc4834e5433e2ee8f64658ccadc55c2bb413f8e61f1af22e 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/notes.html f6c8f613c12cf6403617ed31786eb7b476cf5f3ad5a21ded5f4a29a4e5c9dc6a 2 @@ -3904,5 +3904,5 @@ -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub 23f2fba7a4df97ae917e0d306d958e484c6df3e64320ca83a63bca7f919a60f9 2 -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.html e3671b8d1d7c1ab33d278f9f04e81e068a30d88ca9ae154131cfbad028e22942 2 -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_advanced_agent.html a6b854c89e890e5b40fe294fa18684cc299d1c02c6da8286321499b67f158b39 2 -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_agent_config_files.html 9811348cb0b4d2e9539d1a31cf2e3b0fbd3fb992510a1de0fbf8cb64f512668b 2 -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_agent_funct_descr.html 308e851d95337cb23599a89f006a0ee5ca3c616aadf6668dddbd190f8aa6e1d2 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub 5b14ae1e3c5766c558335ebd0be3c7c01e458be2953243ff9c13c3b76cdcc361 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.html d31b87582f132753675ef15306d54251fa6f8bdcd548c09a6a4511258a3ea4d3 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_advanced_agent.html 5632564855ed758feaea74693a93cfeec18c48ff21af6b8407358ca9c84771fc 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_agent_config_files.html d6e7f1ae9a52217806c72b445372fba1036fef8defd3fb95f825d932cfe567c4 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_agent_funct_descr.html a318dabbf5af97c81b175ce7c6395328b96000807c955d766956339d7277b901 2 @@ -3910 +3910 @@ -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_app.html befcb1b9369ab1504e0235a7169f2b8b5c6903d87cf252894c5ae7b41a25c652 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_app.html 7e45f50ee28b89f00efbc19dad9cf70349432cc63f2d808d313cce2c94baf4de 2 @@ -3912 +3912 @@ -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_app_b.html 91f74cfcf5e6884edb3453f3d2628055ed63e419869029956f10eec9f2d1e4e3 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_app_b.html 78aacdb970ac7b3acf142c4dbf53a3ef9ea403c56e1014030d9b896bd22d2805 2 @@ -3916 +3916 @@ -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_config.html 3d4c51dc4d503f03099e430da4f67a7f81772f7ef7c95c4f34c5c3ca4b27591f 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_config.html e9e6cfd6e16379151c5523627114af2619a499d7f825521a003450494588d14f 2 @@ -3919,2 +3919,2 @@ -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_generic.html cdb5c688b99cc2b535dd88055d7197e4cf5470ec5a36f0b50533e119dc70ecaf 2 -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_impl_example_agent.html 93a554308e7fca2c2be316b719e5a4d3adac6df0351a2645e080986ac0f83fab 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_generic.html 1c68676312930e9ba171b7b253332f74441bfed047f3e9a76d0687d242297401 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_impl_example_agent.html f63632c24fe9cfe18ceb2826b429e22686444d7e3c0abd754e0c5dffac9d95f6 2 @@ -3922,2 +3922,2 @@ -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_index.html 5721cb850d79a0d72ae0470829dba45ce58e8a9f1b07e8c8e6a6635549dedd46 2 -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_instr_functions.html a6ee7491e086fa8922f29b2819d36c2c97e74572c4c489b8198b13161808d080 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_index.html f2a791e382054b05a2d0a863c7b9efb48f0a720441997f7f9559c7fd221a2e48 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_instr_functions.html deae655b7a8352cd432f0df17423166451cdb220931be07a836776f8f26d8d5b 2 @@ -3925 +3925 @@ -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_manager_config_files.html ddb209bfe7cd93d5bcac8fa2248a89bbfc908b751c726a539ad89355f22fdf38 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_manager_config_files.html f01a9681321fa42e9901eb1a62a68cca0e4f84923041106e9473c8a822d1526a 2 @@ -3928 +3928 @@ -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_mib_compiler.html f328d4e0b0f34e00919f9b979ea4e06cceaaa8caea96b36eb625002c3f79013d 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_mib_compiler.html 42833a2593523dd11509b6173bd3abace68201057bd820f36fdd74c729a0a342 2 @@ -3930 +3930 @@ -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_pdus.html c92b2c3394384bee01ce095003a8aa917b1e3e582f1d8f36c4bb7f41a64b5cbe 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_pdus.html cd22ec7a307bb79d06391c294236a99b50d700dbe18eef74aabbb00648338a0a 2 @@ -3935 +3935 @@ -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpa.html 97f305355f319f412e6edf5258dc404b6b3cad13d848ae0bd6393578d868f64a 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpa.html 21accabec4092f0ed0e8c213a5b9f09708f14522c97dea573f366146d23b181a 2 @@ -3952,2 +3952,2 @@ -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpc_cmd.html 5a4180c7e6b8ce3101167501f972b9f8261ff83640dfeffd70117d8c9fb610fe 2 -/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpm.html 5642acd342a007b4d8330be63dbb1e9491e69800217080db98dec1514e78b969 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpc_cmd.html cb4a1380c5077d510d5712fccf2f8c9dd051a2488235f4fb6641e12cb339e918 2 +/usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpm.html 62f576fdeeef884f8014581efcb419529c600b9149b0f385fa71f3cfaa1e61c4 2 @@ -3968,2 +3968,2 @@ -/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/configurations.html 1cebc15ba369e11148225c39ff7623bea994a4606a8c721b1eada25f3c387c0a 2 -/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/configure_algos.html 6e579d651c6e8a7dd1b65519cec19da59f64d52b24d69a7b88a9f3d45157edf0 2 +/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/configurations.html 3ff137bc07c449a4f447e4de05e3af7f25641c9b86c0abaa008f24b4142df389 2 +/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/configure_algos.html 815a90beba7692b57b838bd6fd3a24fc2bb94270a246f37f4ac1e33f07a57529 2 @@ -3980 +3980 @@ -/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/hardening.html 7dcff38c860200c42f499283625002882bb9a66f8f9db745d2b2f1cee93c2906 2 +/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/hardening.html 6c1aa0df1f6d07d50c927f890fa35d5e35b317a17ca5cbc9620f83884a73d784 2 @@ -3985,3 +3985,3 @@ -/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub ab51e17ea0388cde2fb8247dbcd9f8bab8d3d7a1717f8cb7ba1a9bd3f47efd1d 2 -/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.html e3b3fe97c06e130f64025f79d3905fea1e52c73a9b3da66d4139ac1babef513d 2 -/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh_agent.html 13085ad7b88cd6ddf5f936efe96f54d1bc8b00cdf01855c9cd2052a511d9c240 2 +/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub bd9a7549272a5861e8e2ee97ff816a602402c6392adf7bc12a9d83ad46c5b104 2 +/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.html 5ae04cb2b8c0600c6c28ea1cc8f5515ddbfc81a3109b4084c7bad692df070948 2 +/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh_agent.html a2d08d7ba0720466c8c682a909ffa1b4aa20b9b2563fb6fff6f32539240953e7 2 @@ -3998 +3998 @@ -/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/using_ssh.html 8fa8cf20939b8c3838ef5e292d2b036264a75ec8a49a00d698285b76c075037c 2 +/usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/using_ssh.html be87fb56c4d2262002ae652eb7d9207fc595093281dd2cf41ba7b32eb0000e2f 2 @@ -4039,2 +4039,2 @@ -/usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub b660f721e41f13508b2271d79f59373461ea3e88eefa31700111343cefd58717 2 -/usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.html ce9eda3f69996b5d56d702926c93267148bebe78a4e56eef0202fbb3fef610ee 2 +/usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub 968884e6caaa12d0345f01e72ab58ca5dd970cf7b838610ef411a03df72b9351 2 +/usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.html 973f3571a6a25e1f612df0843c5c3f9f1deeb642a3df422aa55a9d09714f6d8e 2 @@ -4044 +4044 @@ -/usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl_distribution.html e4655017338ce14c1e2e81654a437e6e4758e89f07eb720db777f18721e32446 2 +/usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl_distribution.html b9f2bb66f9c9343ced7c4e73b24ea9ae8aaa4cc97c8cd7a3ec3b1163fa6a9628 2 @@ -4048 +4048 @@ -/usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/using_ssl.html 20c377d6669c58a1c6d2d2b276cea9d41c2d7c48fa1e8e541788b916aa36ab3f 2 +/usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/using_ssl.html f11923114ca37935d62f483d415cce17530628d7325c76f9649c53731ce7dac1 2 @@ -4056,3 +4056,3 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/argparse.html daea18de8acb690a31b133966e496ff482a711e4ac788041bd18dfdfefdd5517 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/array.html d42f9f609f0e0ec80de2c0fda05c966d2a04d8d027a6658954c28a6cd97b74f1 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/assert_hrl.html c2db8a573ba4e5acf26d7f4aee86214c2b9928ae38ed3d0e31ad1e7f8be53b49 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/argparse.html c1221b7cb3974e8654d070cb4c8a13223879967a719fd30591956015322903cc 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/array.html 6e5def9ed54a7261b2682f5320610c11a79e6c4810ba6127ffa67125b758da4a 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/assert_hrl.html 797edab0aa8dc169e50dd3eb31d2d13426c121c11e2330db53af91401b98fbcb 2 @@ -4063,8 +4063,8 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/base64.html 575932e10eff1ce39e6509598ea24bfa798f290c10fe1b8ec250d753f85c97e0 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/beam_lib.html d49e45e1107a92e9e59070298f694948e238980cbbb94a7fc08b775241f27ae9 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/binary.html e0f199165498851beaf979fe41a910e606e5b48809d239a0083dace74b45d7cf 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/c.html 9f83f115b7b79d8d6ece8e94d9f5b2eb1450444ac40d5db9b153d23c15a68fe9 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/calendar.html 2b0edae75bfe9f10ee649a5067ccdc1ee3f78713d89a6191be0736f1eff39dfc 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/custom_shell.html b3736e573748023f527a8cf397fbb3118ca69a498a88b3b335f72ec469f60a3f 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/dets.html 4bbd9f766b4b95e1f4c2004e0ef3f60a03cfc25b7705e12af9e48559757686ea 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/dict.html b0aa9696ee03bd53735de53725814d6e0dda3635ea72c453d598cf2d121cc64a 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/base64.html dd3237677c1c8cc79fb127b7527fc3fc619c7ade481e489324ddcef0bdce45d3 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/beam_lib.html c496ad46e66a254b441bb852110318065b1b51ceb3a54989a917e1c557f96e02 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/binary.html ccfe412c42067624e981b14c91a4fb12d968f0c166acad3586c7fb8088e43150 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/c.html 87bad830dab2984a74b896e66cb4aab7605ceb4e4b9343cb9a9a20a3eb9d4b10 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/calendar.html ce84584996ab486010d895e03ab6af5fd185ca88fdbe2442538eb1a1c0dfd1b3 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/custom_shell.html b302a67528f237621125043f2eacf93825816a85a4e2219b23a1c2733ea3bdbc 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/dets.html d9983554a558ddd44c7feb5ffd4e33194c6fbb948f541745025c58d448569509 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/dict.html dc2a75eb82bf92f307522e11433edd6408342b104c00de179dff008b5cc176c5 2 @@ -4085 +4085 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/epp.html 3d12ae7d7b4d2931fad741073b1a9a3ad1c7f8cfbc9dece0173e64b934689e8d 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/epp.html 6d6637fdb65bf8f70a72c7b896345b9d66af75afb07ee9c2fe8d8e90ce2844df 2 @@ -4087,2 +4087,2 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_error.html c60325e653613aca18278fe80c1a88b3cf70ef3537a858ba554c2ae82eb7d292 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_eval.html 73422db9a2e5447dd690b2d268451530ce1a3af9c796b722c9b894220f09e715 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_error.html 4a8f4e00a90d4b08e4faa210f6b170c0f0e3da64b43325eac0ef8043e2b0d661 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_eval.html eb361036c0dd18a482b5571c1a6b895970a444020a5d41362eb77d2defbda72d 2 @@ -4093,2 +4093,2 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_lint.html c400306b54c906be5f718f7f2dd433b683e96888ffe67da86d6ee463b904b05a 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_parse.html 4a229ca2c1b11a0ae3b94b61b6eb8d8ad790022fb90ef3f56198d66c925a747f 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_lint.html ae53d7a984b1c0990692c7d09dd6871607887cb3b5459ac19590ec8199925b08 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_parse.html b943d41ab08dd048a96480f9d13e5c7ce97a0a21c8ac98e8239dd27f84931807 2 @@ -4096,8 +4096,8 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_scan.html ad36533ca28f231c9b6394fda4efb474965ef609cf0bf940635675a9640e1e6c 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_tar.html 8b9c7b5b56b95bfa57656e54b6028e52dc19b49a0fa053ce6952eee903425eef 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/escript.html 095a08e80ccf80a2353fba8565bde0948933561d116ef8488cb9c8410b6c12ac 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ets.html c3f6ba53d1d6c5ed964268950b4ce5c418d44d089ec6d93dfbd9eeba81b27fb9 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/file_sorter.html 737f758faeb34f131fc4f736ebf11b03cdcaabb2531f5eef1fc395ef4ed3e2e1 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/filelib.html 73bf254121c3fb2410ab60b8ef534b17ad434194e033b69737bdb39dde40b00e 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/filename.html 938d246d00596e657333ce85f194e3c5c31f5f27ece3ac0641b8ecb853533c98 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gb_sets.html b5a3baca73a2d689f4df9edf7d986405a8deeb633f722dff69b0c846a73581ac 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_scan.html 2c05cee51835a66c02f98be91eaf6f950e096217501d2879834066b98fbffcea 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_tar.html d277b5ca23b21187ec10f68193a2362ae5293898b9cdca488a37f398b8c260b9 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/escript.html d3c1725f1daa7295bbd88c8b7f46bd3f0af73fd5c6edb5e717fa141cfbb51a41 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ets.html 1488f5310ce80af3094a25be45131a0ad4380acb85007d922db0d0cc40dcb455 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/file_sorter.html 2565b18d28ff4c0d5cbf4cbf59983d11febc9b0cb544a8adeccb61e171c0bea9 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/filelib.html 14b8c9162db8f0687f5f40ca9fca0e2bbb22416f6af01c4d5e4ab14f983f637f 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/filename.html 337276d3e6793a6f1f5714c88ec4bcb242610e36a07721bc452e9700a869851c 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gb_sets.html 2fa87648384c231f420f5e30074d7c9327f4998b91c950aa758a086d2664e530 2 @@ -4105,4 +4105,4 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_event.html 8578e9ea53348d4d4b1afee947aa00713ca888cb47fadd0ed5a9d9d9edfcfc4b 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_fsm.html 3c36ec5eeb410d32684e167ead5486aac09982b39ddbb307b3063ba77205e8c1 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_server.html d28fe02eb8d2774d741268248e3e508feba8d0c7904987b992c99095a2df3365 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_statem.html cd0a1b412be2186a615168e2fde45a1c45fcacdf256ee4468d2962010eabf4a5 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_event.html 7ca874b20e164859671004596b3de1a173098cc5bbb5bf2feabfd402fb05dd65 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_fsm.html 5158a87ed542ba49cf2806d6b7700ea419fc6ecd211762e3069bf9f2710ee4c5 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_server.html 45dab135d89cbc05f92f63ffb49104407b67a5687ca3acb3818544ad69165289 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_statem.html 970c92f63cca300760a22a0f5ff6712f466eb18cb2b45e020315f5d4ba6c09b6 2 @@ -4111,5 +4111,5 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io.html 71ffafd70a254ab5be7b0939146ebc44c10ecf9e611c4d3b1046c496a8a35aac 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io_lib.html fca86aaaac4aebca50e24bae5c4ba487fc4462aa6afdc2dc6f24a08e8f084bbb 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io_protocol.html 844919f0c65b1bc5f0b7acb5a1746317560583a467c74fec8c5ecfda79fdedb6 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/json.html bb962b534508bfc41b7a2b5c59e06134aefab2f33b4f26103b63d10c016aca74 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/lists.html 3a06357eb61d06bc501d9e47aba0ddca7b60821f371545692378989198d3c980 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io.html d2262a90338e1df664ce710bb7af01b99c08144838b7c685561cc038aefb3f89 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io_lib.html fe06de91849d3ebeba399a52782ccd35291bde844ff2575ffea22acb0fa7aa06 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io_protocol.html a17b6312b7f89d949f66ffac5d3d4a880030eab4e40186e3b66f5999b6142ecb 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/json.html 4228b5e5e4c211fab3a975fc43eba7c55334d4b692d6e10a3b17c675b2213319 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/lists.html 759b9acd68c0d15c77176f43c70116d61ab7c2529b67c18dc82ec848dc90dea7 2 @@ -4117,7 +4117,7 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/maps.html 2757e8a7e6b78e4c4b5e1a2c36ec3720fb73746d02eb704b233f4cace11efa64 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/math.html f1ea50c6e428fafeb11e5876e2a401da2babe585fd228e281a9a038cb4ecbe00 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ms_transform.html ef24c27cf9fc8cf4a0be33a24ad92db021dfca215c9edf028a8e099650c95711 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/notes.html 298b111e553d9583e10ebf5109555871f4cf5cfb925ec4ce71dde2d07df2c0b3 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/orddict.html 8136148b5cd93e342006a083e7ccf4dcb703b51761a63c9cab34b01c5bf99881 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ordsets.html c611674ecaf862c1016aad596c00af0159e31b25d9a0a4b6424ca691e6ec6594 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/peer.html 22f87f9ad684b0816a5caadc560969371770e8d4ac6da3abab3b6fdb4272b246 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/maps.html bc8fb2275c51cefea62d0c3dab6a7492015ddd0b267635992337bfd058c06558 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/math.html fa6e686a6342b434853b1c53af204a79abae3b0b4c33f9a1b542009188fe78a6 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ms_transform.html 6fcfbf334c65c53da38f60fd08bf80fb857f36ad93c12cd9af1b36ffb9179ad8 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/notes.html f98ce99014e63ab7eae2986f6f9d58b95106fc426bab7cefb00ac38d39314029 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/orddict.html f261bab25b4f1e9666b33288ef1725bceea7659fca4a69e66f7e6a6777a3b13a 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ordsets.html e92a279c8723d9027041ba99b0c76ac38a9c849937a9ca822034e75aa240d09e 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/peer.html be79f0290483ee4884babe290dcb92ea04a8e3c2eb8e31655fb54458bad322ce 2 @@ -4125,7 +4125,7 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/proc_lib.html 1f3e8a344ed123ba06b332ac811495470c276edd4fa9940f4961a161fcaec085 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/proplists.html b75a7997399fe3001d00878ab24f8924fc0e7b6339ef3edd6d0e2235a0043d3f 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/qlc.html d33d213f0294224689db2bb033475266f407b9be2ca1ce4d09b704805128fe98 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/queue.html d5d7ff3faa8cc3113fc1468bce55bcd53d2a16c3d6d0311bad3e9b44bb6a0420 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/rand.html 2cb328e3cde0c382dc988eb1772dc972ed995a3e1a7a2ea946f71787dab7e1d2 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/random.html ea5f20974283641737fa25f5710fd346880fa0d073b0617dcd4a37d52f5dbcb9 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/re.html b9ea38bd8e4dc5c5ec85c94f587cc611ff8a3cedf0ecfd58b70449fff2ff012b 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/proc_lib.html 97578c1d928715432f82b123e486f532df1a8428fd886abe0484fdb1925ac90e 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/proplists.html 1a710a36a528f1bda30694749728a34cc8907c507d0b6bd08f215f7b5659ec99 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/qlc.html 83b6101c117a36d8fb66cc466c579da35d33fd186acf2a12d957c5a1db8bba6c 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/queue.html 78ffaf9aa414cb52f352270586dc7c8a41bd9bbbc9c3cc578cdd84961ee6b28e 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/rand.html 33a3038e5e87924f95aa2430b16d8063084499a1bba0272f6b5e1d3ba8b3eef8 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/random.html 43323d773e30e06b519e88713a15cf230e38397e54000c1425b6c782f3a36f12 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/re.html 95172d8c7a73b163456c469e96a9f7e97f848bbe553c0709a44784d649cc39e6 2 @@ -4134,3 +4134,3 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/sets.html 561049f50802549e4cba377cc532af6ede72318b3aa074c8c2107ba5e77e9398 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/shell.html f7f93deb2d1cd9d8a801cb7937159b51b0911a2deeb5263a0033f2ec55215cfb 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/shell_default.html 6d4fef2c55d772615b2f1d759d288131af10958531526f9149af502c4745fc24 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/sets.html 26df98d297bd38d34e255beee43ef00f52f94f95d021177df3e120afa9016a45 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/shell.html 1ca2c07490390fcb76a6f63185e1e234b10da40c29b747e8f09a1d964dcf71c4 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/shell_default.html 1b9949204521afc1f53d46b4b3fd9278ca2ac1ce72a172886a534623af7b77e1 2 @@ -4138,6 +4138,6 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/slave.html ea6a2b31e6f353b4546074f59ff6722b334ed02dc18b27f79e3ab489005ea874 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/sofs.html 7f6f6296076ff57216a01a183aa99bf2df96f446045764f652e8a886ebf8a2cc 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub 84e58102070521648f8a638d399e59694e7c20fe75acf5b1a8a86f0a7151d046 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib_app.html a1d2a3972e6fabb249b130421335e738abb4b0fea3c0cdc20e0b0fecdae41d53 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/string.html 503361036fc4a6af21a16b5b88aab4847fb0658fc82d5c1d619902794a01d224 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/supervisor.html 144cf37fab73a1a5456fc4876b394c29de4943670a23926910d0c6a24fe5cf06 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/slave.html 5698dc504e1b2f1c89dbe353bf7ff11269a911f403a19bde9ff04e22da5e3834 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/sofs.html c7b856265f9fa148dbef117f9dfd5e9e94bf03b6dc35b4adeec9bff4fd11a26c 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub 6eb1b501284748c1d9a919e57c0b3be6c77e9930e364a43b526fbdee7079051f 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib_app.html c37be34e6eb174ff3d58056a1b7fffc98dec1ef24e5ce3d173b2a5aac66a2852 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/string.html f6d72fb70e526353fb203fce1950ba7065d4845e8bd72550cbdf0299ac8e08e5 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/supervisor.html 1c798471a7833435587ccb0240c0b1791d935e57a8472916d1206e43f38d8456 2 @@ -4146,6 +4146,6 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/terminal_interface.html 58a803b86d961a75331ceaffb54990ae9553cae8dcfbf4636fe87c75c81c0109 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/timer.html d555a234860df44f3544699d2af4cd36aba25b3d0864b111d332beb34a9572e1 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/unicode.html d910acaa46b474fe25329a795ee192b6e5f9f379e89190e78bdef71b79a6c9e7 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/unicode_usage.html 10a9e467079702720aaefe110c949984aa458642a5b879bd85fccf9eccf35e07 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/uri_string.html e72310f097f2a7bd7e043efb3cde417cb996315261e47a52a143010362909b64 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/uri_string_usage.html 26bfdb0c3acfd0f1f25039bf3ecf1ae7e54cd9ee4629fec2fe10abe91b6095fb 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/terminal_interface.html c545852e998a7e1ba8f343677225456e67efc0ad49e6bfadbeea22553430e6ba 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/timer.html b554a3c0ddad8726724382ec422cc126b83af05aaaed943a31507ea565f049f7 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/unicode.html 8b4235613a1f8c140f57dc0e84133fa5815264f3782e29bda29432503dd1199f 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/unicode_usage.html 12e0480ed70a3ee7944b3f37d5d5a051b3ce0eeccbe90796b9d3be34168f4853 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/uri_string.html e3f8b250329e777bf5d7781d2ddb07e32069fea612f09416c21db0c6307300dd 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/uri_string_usage.html 07bca4980d79d12a84eac59990c10324440d5562b9ee89c1df18c7c09357926f 2 @@ -4153,2 +4153,2 @@ -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/zip.html 1888d64199118768c8e2b34837d00000e12c851913c5d172e69cc021d247bcf3 2 -/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/zstd.html 582ea46df4966e74e7fbfc395959fc06b26dfdbb2980b7fdcaf651755acc19c2 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/zip.html de8aad34643bba109f178539912fcbce6c0463cc90646c0bc47422d16da480ff 2 +/usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/zstd.html 71af18f3ae6098c3b16123c3b2349a7beeaceae6b2039b3194b4a4a460645fac 2 @@ -4180 +4180 @@ -/usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/erl_syntax.html 4580d32d8a6bb8e813f5fd68741e02748de1de79294ef8d199ff76bdfde207a2 2 +/usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/erl_syntax.html 239aca9b29bf4f38c809681e5dec286ef19536b81993a54233819efc4d59fad9 2 @@ -4183 +4183 @@ -/usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/merl.html f2ab61ddce1086ae6712b104c83bc617c9dacaaf7de87850c097c55c1b2efb41 2 +/usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/merl.html 2aa949cfaa443e60419df359f76799c8b08ec575f645988bd46e79265aab082b 2 @@ -4185 +4185 @@ -/usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/notes.html 4073142b71ae3c348e3cee3f3beda6bc82172398373dc58ba31bca37c36da9b4 2 +/usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/notes.html 1a8cb83196b5359ce94ceb836810ce4430a2df17678633dc72617bff32419dbf 2 @@ -4205 +4205 @@ -/usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/getting_started.html 9f76a86777db150a339a333dde931d2a84dbac069d633532ac01e7e5291fdbca 2 +/usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/getting_started.html f87b6771b82dd68eeac0f1fb287ef1335fe93cacd23f2c61421c20bcba41e64d 2 @@ -4210 +4210 @@ -/usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/tftp.epub 6c186ecb0130e6fecc2c18f87f1e3eb176a67b6080601890a2a04bb679d0145d 2 +/usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/tftp.epub abb58e3679ef3a2eb59877afc4935941c1727ff92b62b89fb2bddc3eeba362b9 2 @@ -4224,4 +4224,4 @@ -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cover.html cdc49f0ed27553d3efe475a4c573918038a4d03dd941c32483e902f8f34608b0 2 -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cover_chapter.html aad8b837af6ce8abef194688d45b060c2a5858a6cf47cdc7e6bdb029919b0f72 2 -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cprof.html 194d39098059cb301fb4c3145c50a6a4c935e583ffd929042769f253a7dfdb38 2 -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cprof_chapter.html fdbbf66be0d214724d17a45202cbb707593c63840f8e137d5484a7cb3a20008d 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cover.html e848f2de86faa3d01cd8160cd118739abc563dd35dfbf774e44e87b431415e55 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cover_chapter.html 12d314923a81befeca624dd02dbc0fca572108768368984c9e701e63f5facb6b 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cprof.html 6bdb2ccc0cbc0780aaf0cd647f40a91f0fcabdfa0d5085d399a9df819de641e2 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cprof_chapter.html f00679a9835ae9023ed8159500047bd9879f26f0c9679ac7c0bfc188273141d2 2 @@ -4239 +4239 @@ -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/erlang-el.html 73cd9bb3bef02ed6b4d10104678ff5f006939cb8b2cccd12c3cf0130f043a00c 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/erlang-el.html 12964c17b0126343169c7e879bd97afca0e02bdcdbcf585612631dd548ef863d 2 @@ -4241,2 +4241,2 @@ -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/fprof.html 64fc0397edc0a45e9e761871fb3c1a9b4c8c0c02ad1bdd4dcd5edcfcbb0bcde3 2 -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/fprof_chapter.html 5c47f75db997aa27b2acc5cad7cc2aa877b64b7e2c8ab82d9bff02708d589ac7 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/fprof.html 20e5b0de0f15df9a9a375d508b86822131916b1f6803f968d53cda1df5db0346 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/fprof_chapter.html 60fd4913857e9b8be80b54f90d68033dcce1f5f58c3e389a9edbc682de0ab436 2 @@ -4245,3 +4245,3 @@ -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/lcnt_chapter.html 80092c36a629e87c9133534fbf50c5e9ca9238a8d60bc1330966ca37f66a6e05 2 -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/make.html 778fa85b12c0824d31e52e9fca8560632b0be5a067c7772049416f3f156377cb 2 -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/notes.html 46fef87ab4bbebfa06079a30f764ac6837c4e4862adfa3c78eafba5134f6aae4 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/lcnt_chapter.html e1b478b7a23b609840bc9707caffcce619dc38771592dd2b5f94a74c1801cef8 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/make.html ca8e2ed7c339cf13a78030e6d5bbc4b945d439723479b0b4072d711634985328 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/notes.html 6f47d2bc99ab5edbe9f727937aef874c9b39bb9819837342c5685581a1cf87db 2 @@ -4250,2 +4250,2 @@ -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub 39bc1658dac35804fdecc83bb9542c7ea118705f989b37d586d77db8b21f4519 2 -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tprof.html e72916cd89feb433be088081e42d1fec3baf40d399c9de3e0372dc5c2c69e1d0 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub c05e8ccad9dd667efc49cf5e902e1f56acb0b998270d128d366a2f47d3d0ed63 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tprof.html 0261af325ff7d85908219df374c2741046802880ba0bbf7e014e42c77852832e 2 @@ -4253 +4253 @@ -/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/xref_chapter.html 423e1fb97595afa30d62ae23adc3b962af727b3feef63416758fd82467dc93fc 2 +/usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/xref_chapter.html d56235134cdc1754dd27bbffbaba130d62f056631189ddbb086e9270d74c58d9 2 @@ -4339 +4339 @@ -/usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/chapter.html 019c425522bc0e98527ea52fb1176a04849c9156e86ce39d4aa7080490da95de 2 +/usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/chapter.html 1e38f464e7401ec4eb2f36737d5a926d07cbbce363e0fa14c465ed7f5d71b2ba 2 @@ -4355 +4355 @@ -/usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx.epub e2e6d29c4d8d534218a6ce0eee5144749f3d27b4d8643f2f36d25742c5bf57e4 2 +/usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx.epub 939c7fe9d591bfc362dfdf5a8440440d4afe46afc56c53348b34b2b209e4f603 2 @@ -4591 +4591 @@ -/usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx_object.html e3f17e11fc9e189e2e30f15e53957ce6239365ee069623d33a7a070b0a7ac0a4 2 +/usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx_object.html c588d0f60c39dcb66431da207ea7c6ea5d33c2745ca0e781fa0d38ceadb3a701 2 @@ -4625 +4625 @@ -/usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_examples.html a617986444a1d47e2257ae39de9299f86b0dc5126bd8267c5b532506b78c127f 2 +/usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_examples.html 15ca98ed6f7803796d38b256d58ad329ec3bfbf7106ff9b3665dfb2141bfe418 2 @@ -4628 +4628 @@ -/usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_ug.html de5a4b9951ba3f6ceea06083ec718d163eae4c39e316e969c9b1d37b730b02d3 2 +/usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_ug.html 7dce1e5a2644dda4cccbf474402eb3e5385aacb5fdfd863d61dbd48fd531ed28 2 @@ -4631,2 +4631,2 @@ -/usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_xs_examples.html ab1b06b8004434a7ec473c8236153c90ecf7695a2222b32db3327f67b2562cef 2 -/usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_xsd.html 59148b4821c9d3807593e9ee01c731b7bc0e3c47c013c8b5f452aaa9c0e3b361 2 +/usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_xs_examples.html 65083b8e8a063fe1c1525eb0233e7bc97dfaaada1cd5a7d636616050fc1d7937 2 +/usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_xsd.html 55c123b1833ce07c0bedf88d4d277cfca40206b8585a31ef4d518130b30172b4 2 comparing rpmtags comparing RELEASE comparing PROVIDES comparing scripts comparing filelist --- old-filelist +++ new-filelist @@ -554,7 +554,7 @@ /usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/dist/lato-latin-ext-400-normal-N27NCBWW.woff2 2 (none) 120777 root root 0 4294967295 ../../../../xmerl-2.1.9/doc/html/dist/lato-latin-ext-400-normal-N27NCBWW.woff2 /usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 2 (none) 120777 root root 0 4294967295 ../../../../xmerl-2.1.9/doc/html/dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 /usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/dist/remixicon-QPNJX265.woff2 2 (none) 120777 root root 0 4294967295 ../../../../xmerl-2.1.9/doc/html/dist/remixicon-QPNJX265.woff2 -/usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/dist/search_data-B18D77D5.js 2 (none) 100644 root root 0 4294967295 +/usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/dist/search_data-0F342CA6.js 2 (none) 100644 root root 0 4294967295 /usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/dist/sidebar_items-0FCC6507.js 2 (none) 100644 root root 0 4294967295 /usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/doc_storage.html 2 (none) 100644 root root 0 4294967295 /usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/edoc.html 2 (none) 100644 root root 0 4294967295 comparing file checksum creating rename script RPM meta information is different Extracting packages /usr/share/doc/packages/erlang-doc/doc/system/Erlang System Documentation.epub/OEBPS/applications.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (996)) --- "old//usr/share/doc/packages/erlang-doc/doc/system/Erlang System Documentation.epub/OEBPS/applications.xhtml" 2026-08-05 05:56:49.000000000 +0000 +++ "new//usr/share/doc/packages/erlang-doc/doc/system/Erlang System Documentation.epub/OEBPS/applications.xhtml" 2026-08-05 05:56:49.000000000 +0000 @@ -29,8 +29,8 @@ Releases), the code for each application is placed in a separate directory following a pre-defined directory structure.

Application Callback Module

How to start and stop the code for the application, including its supervision -tree, is described by two callback functions:

start(StartType, StartArgs) -> {ok, Pid} | {ok, Pid, State}
-stop(State)

Notice that this function is not thread-safe.

driver_cancel_timer()

int driver_cancel_timer(ErlDrvPort port);

Cancels a timer set with driver_set_timer.

The return value is 0.

driver_compare_monitors()

int driver_compare_monitors(const ErlDrvMonitor
+        *monitor1, const ErlDrvMonitor *monitor2);

Compares two ErlDrvMonitors. Can also be used to imply some artificial order on monitors, for whatever reason.

Returns 0 if monitor1 and monitor2 are equal, < 0 if monitor1 < -monitor2, and > 0 if monitor1 > monitor2.

driver_connected()

ErlDrvTermData driver_connected(ErlDrvPort
-        port);

Returns the port owner process.

Notice that this function is not thread-safe.

driver_create_port()

ErlDrvPort driver_create_port(ErlDrvPort port,
+monitor2, and > 0 if monitor1 > monitor2.

driver_connected()

ErlDrvTermData driver_connected(ErlDrvPort
+        port);

Returns the port owner process.

Notice that this function is not thread-safe.

driver_create_port()

ErlDrvPort driver_create_port(ErlDrvPort port,
         ErlDrvTermData owner_pid, char* name,
-        ErlDrvData drv_data);

Creates a new port executing the same driver code as the port creating the new + ErlDrvData drv_data);

Creates a new port executing the same driver code as the port creating the new port.

All contained terms of a list/tuple/map must belong to the same environment as the list/tuple/map itself. Terms can be copied between environments with -enif_make_copy.

  • ErlNifFunc

    typedef struct {
    +enif_make_copy.

  • ErlNifFunc

    typedef struct {
         const char* name;
         unsigned arity;
    -    ERL_NIF_TERM (*fptr)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
    +    ERL_NIF_TERM (*fptr)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
         unsigned flags;
    -} ErlNifFunc;

    Describes a NIF by its name, arity, and implementation.

    Example:

    (a@localhost)1> nodes([this, connected], #{connection_id=>true, node_type=>true}).
    -[{c@localhost,#{connection_id => 13892108,node_type => hidden}},
    - {b@localhost,#{connection_id => 3067553,node_type => visible}},
    - {a@localhost,#{connection_id => undefined,node_type => this}}]
    -(a@localhost)2>
    +process.

  • Example:

    (a@localhost)1> nodes([this, connected], #{connection_id=>true, node_type=>true}).
    +[{c@localhost,#{connection_id => 13892108,node_type => hidden}},
    + {b@localhost,#{connection_id => 3067553,node_type => visible}},
    + {a@localhost,#{connection_id => undefined,node_type => this}}]
    +(a@localhost)2>
    @@ -8589,11 +8589,11 @@

    Returns an integer or float representing the absolute value of Float -or Int.

    Examples

    1> abs(-3.33).
    +or Int.

    Examples

    1> abs(-3.33).
     3.33
    -2> abs(-3).
    +2> abs(-3).
     3
    -3> abs(5).
    +3> abs(5).
     5
    @@ -8625,8 +8625,8 @@

    Returns a new tuple that has one element more than Tuple1, and contains the elements in Tuple1 followed by Term as the last element.

    Semantically equivalent to list_to_tuple(tuple_to_list(Tuple1) ++ [Term]), but -faster.

    Examples

    1> erlang:append_element({one, two}, three).
    -{one,two,three}
    +faster.

    Examples

    1> erlang:append_element({one, two}, three).
    +{one,two,three}
    @@ -8694,11 +8694,11 @@ characters are encoded using UTF-8, where some characters may require multiple bytes.

    Change

    As from Erlang/OTP 20, atoms can contain any Unicode character and atom_to_binary(Atom, latin1) may fail if the text -representation for Atom contains a Unicode character > 255.

    Examples

    1> atom_to_binary('Erlang', latin1).
    -<<"Erlang">>
    -2> atom_to_binary('π', unicode).
    -<<207,128>>
    -3> atom_to_binary('π', latin1).
    +representation for Atom contains a Unicode character > 255.

    Examples

    1> atom_to_binary('Erlang', latin1).
    +<<"Erlang">>
    +2> atom_to_binary('π', unicode).
    +<<207,128>>
    +3> atom_to_binary('π', latin1).
     ** exception error: bad argument
          in function  atom_to_binary/2
             called as atom_to_binary('π',latin1)
    @@ -8734,12 +8734,12 @@
     
     

    Returns a list of unicode code points corresponding to the text representation of Atom.

    See the unicode module for instructions on converting the resulting list into -different formats.

    Examples

    1> atom_to_list('Erlang').
    +different formats.

    Examples

    1> atom_to_list('Erlang').
     "Erlang"
    -2> atom_to_list('π').
    -[960]
    -3> atom_to_list('你好').
    -[20320,22909]
    +2>
    atom_to_list('π'). +[960] +3> atom_to_list('你好'). +[20320,22909]
    @@ -8813,13 +8813,13 @@

    Extracts the part of the binary described by Start and Length.

    A negative length can be used to extract bytes at the end of a binary.

    Start is zero-based.

    Failure: badarg if Start and Length in any way reference outside the binary.

    For details about the semantics of Start and Length, see -binary:part/3.

    Examples

    1> Bin = <<1,2,3,4,5,6,7,8,9,10>>.
    -2> binary_part(Bin, 0, 2).
    -<<1,2>>
    -3> binary_part(Bin, 2, 3).
    -<<3,4,5>>
    -4> binary_part(Bin, byte_size(Bin), -5).
    -<<6,7,8,9,10>>
    +binary:part/3.

    Examples

    1> Bin = <<1,2,3,4,5,6,7,8,9,10>>.
    +2> binary_part(Bin, 0, 2).
    +<<1,2>>
    +3> binary_part(Bin, 2, 3).
    +<<3,4,5>>
    +4> binary_part(Bin, byte_size(Bin), -5).
    +<<6,7,8,9,10>>
    @@ -8893,9 +8893,9 @@ than binary_to_atom/2.

    The number of characters that are permitted in an atom name is limited.

    Change

    As from Erlang/OTP 20, binary_to_atom(Binary, utf8) is capable of decoding any Unicode character. Earlier versions would fail if the -binary contained Unicode characters > 255.

    Examples

    1> binary_to_atom(<<"Erlang">>, latin1).
    +binary contained Unicode characters > 255.

    Examples

    1> binary_to_atom(<<"Erlang">>, latin1).
     'Erlang'
    -2> binary_to_atom(<<960/utf8>>, utf8).
    +2> binary_to_atom(<<960/utf8>>, utf8).
     'π'
    @@ -8979,14 +8979,14 @@ binary_to_existing_atom(<<"some_atom">>, utf8) will fail.

    Note

    The number of characters that are permitted in an atom name is limited. The default limits can be found in the -Efficiency Guide (section System Limits).

    Examples

    1> binary_to_existing_atom(~"definitely_not_existing_at_all", utf8).
    +Efficiency Guide (section System Limits).

    Examples

    1> binary_to_existing_atom(~"definitely_not_existing_at_all", utf8).
     ** exception error: bad argument
          in function  binary_to_existing_atom/2
             called as binary_to_existing_atom(<<"definitely_not_existing_at_all">>,utf8)
             *** argument 1: not an already existing atom
     2> hello.
     hello
    -3> binary_to_existing_atom(~"hello", utf8).
    +3> binary_to_existing_atom(~"hello", utf8).
     hello
    @@ -9021,11 +9021,11 @@

    Returns the float whose text representation is Binary.

    The float string format is the same as the format for Erlang float literals, except that underscores -are not permitted.

    Failure: badarg if Binary contains an invalid representation of a float.

    Examples

    1> binary_to_float(~"10.5").
    +are not permitted.

    Failure: badarg if Binary contains an invalid representation of a float.

    Examples

    1> binary_to_float(~"10.5").
     10.5
    -2> binary_to_float(~"17.0").
    +2> binary_to_float(~"17.0").
    /usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erlsrv_cmd.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
    --- old//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erlsrv_cmd.html	2026-08-21 04:00:18.192286748 +0000
    +++ new//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/erlsrv_cmd.html	2026-08-21 04:00:18.192286748 +0000
    @@ -231,28 +231,28 @@
     ** A Console control handler that ignores the log off events,
     ** and lets the default handler take care of other events.
     */
    -BOOL WINAPI service_aware_handler(DWORD ctrl){
    -    if(ctrl == CTRL_LOGOFF_EVENT)
    +BOOL WINAPI service_aware_handler(DWORD ctrl){
    +    if(ctrl == CTRL_LOGOFF_EVENT)
             return TRUE;
    -    if(ctrl == CTRL_SHUTDOWN_EVENT)
    +    if(ctrl == CTRL_SHUTDOWN_EVENT)
             return TRUE;
         return FALSE;
    -}
    +}
     
    -void initialize_handler(void){
    -    char buffer[2];
    +void initialize_handler(void){
    +    char buffer[2];
         /*
          * We assume we are running as a service if this
          * environment variable is defined.
          */
    -    if(GetEnvironmentVariable("ERLSRV_SERVICE_NAME",buffer,
    -                              (DWORD) 2)){
    +    if(GetEnvironmentVariable("ERLSRV_SERVICE_NAME",buffer,
    +                              (DWORD) 2)){
             /*
             ** Actually set the control handler
             */
    -        SetConsoleCtrlHandler(&service_aware_handler, TRUE);
    -    }
    -}

    Notes

    Although the options are described in a Unix-like format, the case of the + SetConsoleCtrlHandler(&service_aware_handler, TRUE); + } +}

    Notes

    Although the options are described in a Unix-like format, the case of the options or commands is not relevant, and both character "/" and "-" can be used for options.

    Note that the program resides in the emulator's bin directory, not in the bin directory directly under the Erlang root. The reasons for this are the /usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/escript_cmd.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (918)) --- old//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/escript_cmd.html 2026-08-21 04:00:18.212286878 +0000 +++ new//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/escript_cmd.html 2026-08-21 04:00:18.213286885 +0000 @@ -89,30 +89,30 @@ -

    Run a script written in Erlang.

    Synopsis

    script-name [arg1 arg2...]

    Description

    escript provides support for running short Erlang programs without having to +

    Run a script written in Erlang.

    Synopsis

    script-name [arg1 arg2...]

    Description

    escript provides support for running short Erlang programs without having to compile them first, and an easy way to retrieve the command-line arguments. escripts are created by either writing them by hand or using escript:create/2.

    escripts are run by directly invoking them (does not work on Windows):

    script-name [arg1 arg2...]

    or by calling the escript program (works on all platforms):

    escript [escript-flags] script-name.escript [arg1 arg2...]

    For example:

    $ chmod u+x factorial
     $ cat factorial
    #!/usr/bin/env escript
     %% -*- erlang -*-
     %%! -sname factorial -mnesia debug verbose
    -main([String]) ->
    +main([String]) ->
         try
    -        N = list_to_integer(String),
    -        F = fac(N),
    -        io:format("factorial ~w = ~w\n", [N,F])
    +        N = list_to_integer(String),
    +        F = fac(N),
    +        io:format("factorial ~w = ~w\n", [N,F])
         catch
             _:_ ->
    -            usage()
    +            usage()
         end;
    -main(_) ->
    -    usage().
    +main(_) ->
    +    usage().
     
    -usage() ->
    -    io:format("usage: factorial integer\n"),
    -    halt(1).
    +usage() ->
    +    io:format("usage: factorial integer\n"),
    +    halt(1).
     
    -fac(0) -> 1;
    -fac(N) -> N * fac(N-1).
    $ ./factorial 5
    +fac(0) -> 1;
    +fac(N) -> N * fac(N-1).
    $ ./factorial 5
     factorial 5 = 120
     $ ./factorial
     usage: factorial integer
    @@ -125,7 +125,7 @@
     If the directive is present, it must be located on the second line.

    If a comment selecting the encoding exists, it can be located on the second line.

    Note

    The encoding specified by the above mentioned comment applies to the script itself. The encoding of the I/O-server, however, must be set explicitly as -follows:

    io:setopts([{encoding, latin1}])

    The default encoding of the I/O-server for +follows:

    io:setopts([{encoding, latin1}])

    The default encoding of the I/O-server for standard_io is unicode if its supported. (see section Summary of Options) in @@ -144,7 +144,7 @@ script (the pathname is usually, but not always, absolute).

    If the file contains source code (as in the example above), it is processed by the epp preprocessor. This means that you, for example, can use predefined macros (such as ?MODULE) and include directives like the -include_lib -directive. For example, use

    -include_lib("kernel/include/file.hrl").

    to include the record definitions for the records used by function +directive. For example, use

    -include_lib("kernel/include/file.hrl").

    to include the record definitions for the records used by function file:read_link_info/1. You can also select encoding by including an encoding comment here, but if a valid encoding comment exists on the second line, it takes precedence.

    The script is checked for syntactic and semantic correctness before it is run. @@ -152,7 +152,7 @@ script will still be run. If there are errors, they are printed and the script will not be run and its exit status is 127.

    Both the module declaration and the export declaration of the main/1 function are optional.

    By default, the script will be compiled by the Erlang compiler.

    It is possible to force it to be interpreted by including the following line -somewhere in the script file:

    -mode(interpret).

    Execution of interpreted code is slower than compiled code, and some language +somewhere in the script file:

    -mode(interpret).

    Execution of interpreted code is slower than compiled code, and some language constructs will not work, but there is no requirement for the Erlang compiler application to be available.

    Change

    Before Erlang/OTP 27 the script would be interpreted by default.

    Precompiled escripts

    A script can also contains precompiled beam code. To create a precompiled escript it is recommended that you use escript:create/2. In a /usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/garbagecollection.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (10114)) --- old//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/garbagecollection.html 2026-08-21 04:00:18.232287008 +0000 +++ new//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/garbagecollection.html 2026-08-21 04:00:18.232287008 +0000 @@ -89,23 +89,23 @@ -

    Erlang manages dynamic memory with a tracing garbage collector. More precisely a per process generational semi-space copying collector using Cheney's copy collection algorithm together with a global large object space. (See C. J. Cheney in References.)

    Overview

    Each Erlang process has its own stack and heap which are allocated in the same memory block and grow towards each other. When the stack and the heap meet, the garbage collector is triggered and memory is reclaimed. If not enough memory was reclaimed, the heap will grow.

    Creating Data

    Terms are created on the heap by evaluating expressions. There are two major types of terms: immediate terms which require no heap space (small integers, atoms, pids, port ids etc) and cons or boxed terms (tuple, big num, binaries etc) that do require heap space. Immediate terms do not need any heap space because they are embedded into the containing structure.

    Let's look at an example that returns a tuple with the newly created data.

    data(Foo) ->
    -   Cons = [42|Foo],
    -   Literal = {text, "hello world!"},
    -   {tag, Cons, Literal}.

    In this example we first create a new cons cell with an integer and a tuple with some text. Then a tuple of size three wrapping the other values with an atom tag is created and returned.

    On the heap tuples require a word size for each of its elements as well as for the header. Cons cells always require two words. Adding these things together, we get seven words for the tuples and 26 words for the cons cells. The string "hello world!" is a list of cons cells and thus requires 24 words. The atom tag and the integer 42 do not require any additional heap memory since it is an immediate. Adding all the terms together, the heap space required in this example should be 33 words.

    Compiling this code to beam assembly (erlc -S) shows exactly what is happening.

    ...
    -{test_heap,6,1}.
    -{put_list,{integer,42},{x,0},{x,1}}.
    -{put_tuple,3,{x,0}}.
    -{put,{atom,tag}}.
    -{put,{x,1}}.
    -{put,{literal,{text,"hello world!"}}}.
    -return.

    Looking at the assembler code we can see three things: The heap requirement in this function turns out to be only six words, as seen by the {test_heap,6,1} instruction. All the allocations are combined to a single instruction. The bulk of the data {text, "hello world!"} is a literal. Literals, sometimes referred to as constants, are not allocated in the function since they are a part of the module and allocated at load time.

    If there is not enough space available on the heap to satisfy the test_heap instructions request for memory, then a garbage collection is initiated. It may happen immediately in the test_heap instruction, or it can be delayed until a later time depending on what state the process is in. If the garbage collection is delayed, any memory needed will be allocated in heap fragments. Heap fragments are extra memory blocks that are a part of the young heap, but are not allocated in the contiguous area where terms normally reside. See The young heap for more details.

    The collector

    Erlang has a copying semi-space garbage collector. This means that when doing a garbage collection, the terms are copied from one distinct area, called the from space, to a new clean area, called the to space. The collector starts by scanning the root-set (stack, registers, etc).

    Garbage collection: initial values

    It follows all the pointers from the root-set to the heap and copies each term word by word to the to space.

    After the header word has been copied a move marker is destructively placed in it pointing to the term in the to space. Any other term that points to the already moved term will see this move marker and copy the referring pointer instead. For example, if the have the following Erlang code:

    foo(Arg) ->
    -    T = {test, Arg},
    -    {wrapper, T, T, T}.

    Only one copy of T exists on the heap and during the garbage collection only the first time T is encountered will it be copied.

    Garbage collection: root set scan

    After all terms referenced by the root-set have been copied, the collector scans the to space and copies all terms that these terms reference. When scanning, the collector steps through each term on the to space and any term still referencing the from space is copied over to the to space. Some terms contain non-term data (the payload of a on heap binary for instance). When encountered by the collector, these values are simply skipped.

    Garbage collection: heap scan

    Every term object we can reach is copied to the to space and stored on top of the scan stop line, and then the scan stop is moved to the end of the last object.

    Garbage collection: heap scan

    When scan stop marker catches up to the scan start marker, the garbage collection is done. At this point we can deallocate the entire from space and therefore reclaim the entire young heap.

    Generational Garbage Collection

    In addition to the collection algorithm described above, the Erlang garbage collector also provides generational garbage collection. An additional heap, called the old heap, is used where the long lived data is stored. The original heap is called the young heap, or sometimes the allocation heap.

    With this in mind we can look at the Erlang's garbage collection again. During the copy stage anything that should be copied to the young to space is instead copied to the old to space if it is below the high-watermark.

    Garbage collection: heap scan

    The high-watermark is placed where the previous garbage collection (described in Overview) ended and we have introduced a new area called the old heap. When doing the normal garbage collection pass, any term that is located below the high-watermark is copied to the old to space instead of the young.

    Garbage collection: heap scan

    In the next garbage collection, any pointers to the old heap will be ignored and not scanned. This way the garbage collector does not have to scan the long-lived terms.

    Generational garbage collection aims to increase performance at the expense of memory. This is achieved because only the young, smaller, heap is considered in most garbage collections.

    The generational hypothesis predicts that most terms tend to die young (see D. Ungar in References), and for an immutable language such as Erlang, young terms die even faster than in other languages. So for most usage patterns the data in the new heap will die very soon after it is allocated. This is good because it limits the amount of data copied to the old heap and also because the garbage collection algorithm used is proportional to the amount of live data on the heap.

    One critical issue to note here is that any term on the young heap can reference terms on the old heap but no term on the old heap may refer to a term on the young heap. This is due to the nature of the copy algorithm. Anything referenced by an old heap term is not included in the reference tree, root-set and its followers, and hence is not copied. If it was, the data would be lost, fire and brimstone would rise to cover the earth. Fortunately, this comes naturally for Erlang because the terms are immutable and thus there can be no pointers modified on the old heap to point to the young heap.

    To reclaim data from the old heap, both young and old heaps are included during the collection and copied to a common to space. Both the from space of the young and old heap are then deallocated and the procedure will start over from the beginning. This type of garbage collection is called a full sweep and is triggered when the size of the area under the high-watermark is larger than the size of the free area of the old heap. It can also be triggered by doing a manual call to erlang:garbage_collect(), or by running into the young garbage collection limit set by [spawn_opt(fun(),{fullsweep_after, N}]) where N is the number of young garbage collections to do before forcing a garbage collection of both young and old heap.

    The young heap

    The young heap, or the allocation heap, consists of the stack and heap as described in the Overview. However, it also includes any heap fragments that are attached to the heap. All of the heap fragments are considered to be above the high-watermark and part of the young generation. Heap fragments contain terms that either did not fit on the heap, or were created by another process and then attached to the heap. For instance if the bif binary_to_term/1 created a term which does not fit on the current heap without doing a garbage collection, it will create a heap-fragment for the term and then schedule a garbage collection for later. Also if a message is sent to the process, the payload may be placed in a heap-fragment and that fragment is added to young heap when the message is matched in a receive clause.

    This procedure differs from how it worked prior to Erlang/OTP 19.0. Before 19.0, only a contiguous memory block where the young heap and stack resided was considered to be part of the young heap. Heap fragments and messages were immediately copied into the young heap before they could be inspected by the Erlang program. The behaviour introduced in 19.0 is superior in many ways - most significantly it reduces the number of necessary copy operations and the root set for garbage collection.

    Sizing the heap

    As mentioned in the Overview the size of the heap grows to accommodate more data. Heaps grow in two stages, first a variation of the Fibonacci sequence is used starting at 233 words. Then at about 1 mega words the heap only grows in 20% increments.

    There are two occasions when the young heap grows:

    • if the total size of the heap + message and heap fragments exceeds the current heap size.
    • if after a fullsweep, the total amount of live objects is greater than 75%.

    There are two occasions when the young heap is shrunk:

    • if after a young collection, the total amount of live objects is less than 25% of the heap and the young heap is "big"
    • if after a fullsweep, the total amount of live objects is less than 25% of the heap.

    The old heap is always one step ahead in the heap growth stages than the young heap.

    Literals

    When garbage collecting a heap (young or old) all literals are left in place and not copied. To figure out if a term should be copied or not when doing a garbage collection the following pseudo code is used:

    if (erts_is_literal(ptr) || (on_old_heap(ptr) && !fullsweep)) {
    +

    Erlang manages dynamic memory with a tracing garbage collector. More precisely a per process generational semi-space copying collector using Cheney's copy collection algorithm together with a global large object space. (See C. J. Cheney in References.)

    Overview

    Each Erlang process has its own stack and heap which are allocated in the same memory block and grow towards each other. When the stack and the heap meet, the garbage collector is triggered and memory is reclaimed. If not enough memory was reclaimed, the heap will grow.

    Creating Data

    Terms are created on the heap by evaluating expressions. There are two major types of terms: immediate terms which require no heap space (small integers, atoms, pids, port ids etc) and cons or boxed terms (tuple, big num, binaries etc) that do require heap space. Immediate terms do not need any heap space because they are embedded into the containing structure.

    Let's look at an example that returns a tuple with the newly created data.

    data(Foo) ->
    +   Cons = [42|Foo],
    +   Literal = {text, "hello world!"},
    +   {tag, Cons, Literal}.

    In this example we first create a new cons cell with an integer and a tuple with some text. Then a tuple of size three wrapping the other values with an atom tag is created and returned.

    On the heap tuples require a word size for each of its elements as well as for the header. Cons cells always require two words. Adding these things together, we get seven words for the tuples and 26 words for the cons cells. The string "hello world!" is a list of cons cells and thus requires 24 words. The atom tag and the integer 42 do not require any additional heap memory since it is an immediate. Adding all the terms together, the heap space required in this example should be 33 words.

    Compiling this code to beam assembly (erlc -S) shows exactly what is happening.

    ...
    +{test_heap,6,1}.
    +{put_list,{integer,42},{x,0},{x,1}}.
    +{put_tuple,3,{x,0}}.
    +{put,{atom,tag}}.
    +{put,{x,1}}.
    +{put,{literal,{text,"hello world!"}}}.
    +return.

    Looking at the assembler code we can see three things: The heap requirement in this function turns out to be only six words, as seen by the {test_heap,6,1} instruction. All the allocations are combined to a single instruction. The bulk of the data {text, "hello world!"} is a literal. Literals, sometimes referred to as constants, are not allocated in the function since they are a part of the module and allocated at load time.

    If there is not enough space available on the heap to satisfy the test_heap instructions request for memory, then a garbage collection is initiated. It may happen immediately in the test_heap instruction, or it can be delayed until a later time depending on what state the process is in. If the garbage collection is delayed, any memory needed will be allocated in heap fragments. Heap fragments are extra memory blocks that are a part of the young heap, but are not allocated in the contiguous area where terms normally reside. See The young heap for more details.

    The collector

    Erlang has a copying semi-space garbage collector. This means that when doing a garbage collection, the terms are copied from one distinct area, called the from space, to a new clean area, called the to space. The collector starts by scanning the root-set (stack, registers, etc).

    Garbage collection: initial values

    It follows all the pointers from the root-set to the heap and copies each term word by word to the to space.

    After the header word has been copied a move marker is destructively placed in it pointing to the term in the to space. Any other term that points to the already moved term will see this move marker and copy the referring pointer instead. For example, if the have the following Erlang code:

    foo(Arg) ->
    +    T = {test, Arg},
    +    {wrapper, T, T, T}.

    Only one copy of T exists on the heap and during the garbage collection only the first time T is encountered will it be copied.

    Garbage collection: root set scan

    After all terms referenced by the root-set have been copied, the collector scans the to space and copies all terms that these terms reference. When scanning, the collector steps through each term on the to space and any term still referencing the from space is copied over to the to space. Some terms contain non-term data (the payload of a on heap binary for instance). When encountered by the collector, these values are simply skipped.

    Garbage collection: heap scan

    Every term object we can reach is copied to the to space and stored on top of the scan stop line, and then the scan stop is moved to the end of the last object.

    Garbage collection: heap scan

    When scan stop marker catches up to the scan start marker, the garbage collection is done. At this point we can deallocate the entire from space and therefore reclaim the entire young heap.

    Generational Garbage Collection

    In addition to the collection algorithm described above, the Erlang garbage collector also provides generational garbage collection. An additional heap, called the old heap, is used where the long lived data is stored. The original heap is called the young heap, or sometimes the allocation heap.

    With this in mind we can look at the Erlang's garbage collection again. During the copy stage anything that should be copied to the young to space is instead copied to the old to space if it is below the high-watermark.

    Garbage collection: heap scan

    The high-watermark is placed where the previous garbage collection (described in Overview) ended and we have introduced a new area called the old heap. When doing the normal garbage collection pass, any term that is located below the high-watermark is copied to the old to space instead of the young.

    Garbage collection: heap scan

    In the next garbage collection, any pointers to the old heap will be ignored and not scanned. This way the garbage collector does not have to scan the long-lived terms.

    Generational garbage collection aims to increase performance at the expense of memory. This is achieved because only the young, smaller, heap is considered in most garbage collections.

    The generational hypothesis predicts that most terms tend to die young (see D. Ungar in References), and for an immutable language such as Erlang, young terms die even faster than in other languages. So for most usage patterns the data in the new heap will die very soon after it is allocated. This is good because it limits the amount of data copied to the old heap and also because the garbage collection algorithm used is proportional to the amount of live data on the heap.

    One critical issue to note here is that any term on the young heap can reference terms on the old heap but no term on the old heap may refer to a term on the young heap. This is due to the nature of the copy algorithm. Anything referenced by an old heap term is not included in the reference tree, root-set and its followers, and hence is not copied. If it was, the data would be lost, fire and brimstone would rise to cover the earth. Fortunately, this comes naturally for Erlang because the terms are immutable and thus there can be no pointers modified on the old heap to point to the young heap.

    To reclaim data from the old heap, both young and old heaps are included during the collection and copied to a common to space. Both the from space of the young and old heap are then deallocated and the procedure will start over from the beginning. This type of garbage collection is called a full sweep and is triggered when the size of the area under the high-watermark is larger than the size of the free area of the old heap. It can also be triggered by doing a manual call to erlang:garbage_collect(), or by running into the young garbage collection limit set by [spawn_opt(fun(),{fullsweep_after, N}]) where N is the number of young garbage collections to do before forcing a garbage collection of both young and old heap.

    The young heap

    The young heap, or the allocation heap, consists of the stack and heap as described in the Overview. However, it also includes any heap fragments that are attached to the heap. All of the heap fragments are considered to be above the high-watermark and part of the young generation. Heap fragments contain terms that either did not fit on the heap, or were created by another process and then attached to the heap. For instance if the bif binary_to_term/1 created a term which does not fit on the current heap without doing a garbage collection, it will create a heap-fragment for the term and then schedule a garbage collection for later. Also if a message is sent to the process, the payload may be placed in a heap-fragment and that fragment is added to young heap when the message is matched in a receive clause.

    This procedure differs from how it worked prior to Erlang/OTP 19.0. Before 19.0, only a contiguous memory block where the young heap and stack resided was considered to be part of the young heap. Heap fragments and messages were immediately copied into the young heap before they could be inspected by the Erlang program. The behaviour introduced in 19.0 is superior in many ways - most significantly it reduces the number of necessary copy operations and the root set for garbage collection.

    Sizing the heap

    As mentioned in the Overview the size of the heap grows to accommodate more data. Heaps grow in two stages, first a variation of the Fibonacci sequence is used starting at 233 words. Then at about 1 mega words the heap only grows in 20% increments.

    There are two occasions when the young heap grows:

    • if the total size of the heap + message and heap fragments exceeds the current heap size.
    • if after a fullsweep, the total amount of live objects is greater than 75%.

    There are two occasions when the young heap is shrunk:

    • if after a young collection, the total amount of live objects is less than 25% of the heap and the young heap is "big"
    • if after a fullsweep, the total amount of live objects is less than 25% of the heap.

    The old heap is always one step ahead in the heap growth stages than the young heap.

    Literals

    When garbage collecting a heap (young or old) all literals are left in place and not copied. To figure out if a term should be copied or not when doing a garbage collection the following pseudo code is used:

    if (erts_is_literal(ptr) || (on_old_heap(ptr) && !fullsweep)) {
       /* literal or non fullsweep - do not copy */
    -} else {
    -  copy(ptr);
    -}

    The erts_is_literal check works differently on different architectures and operating systems.

    On 64 bit systems that allow mapping of unreserved virtual memory areas (most operating systems except Windows), an area of size 1 GB (by default) is mapped and then all literals are placed within that area. Then all that has to be done to determine if something is a literal or not is two quick pointer checks. This system relies on the fact that a memory page that has not been touched yet does not take any actual space. So even if 1 GB of virtual memory is mapped, only the memory which is actually needed for literals is allocated in ram. The size of the literal area is configurable through the +MIscs erts_alloc option.

    On 32 bit systems, there is not enough virtual memory space to allocate 1 GB for just literals, so instead small 256 KB sized literal regions are created on demand and a card mark bit-array of the entire 32 bit memory space is then used to determine if a term is a literal or not. Since the total memory space is only 32 bits, the card mark bit-array is only 256 words large. On a 64 bit system the same bit-array would have to be 1 tera words large, so this technique is only viable on 32 bit systems. Doing lookups in the array is a little more expensive then just doing the pointer checks that can be done in 64 bit systems, but not extremely so.

    On 64 bit windows, on which erts_alloc cannot do unreserved virtual memory mappings, a special tag within the Erlang term object is used to determine if something is a literal or not. This is very cheap, however, the tag is only available on 64 bit machines, and it is possible to do a great deal of other nice optimizations with this tag in the future (like for instance a more compact list implementation) so it is not used on operating systems where it is not needed.

    This behaviour is different from how it worked prior to Erlang/OTP 19.0. Before 19.0 the literal check was done by checking if the pointer pointed to the young or old heap block. If it did not, then it was considered a literal. This lead to considerable overhead and strange memory usage scenarios, so it was removed in 19.0.

    Binary heap

    The binary heap works as a large object space for binary terms that are greater than 64 bytes (from now on called off-heap binaries). The binary heap is reference counted and a pointer to the off-heap binary is stored on the process heap. To keep track of when to decrement the reference counter of the off-heap binary, a linked list (the MSO - mark and sweep object list) containing funs and externals as well as off-heap binaries is woven through the heap. After a garbage collection is done, the MSO list is swept and any off-heap binary that does not have a move marker written into the header words has its reference decremented and is potentially freed.

    All items in the MSO list are ordered by the time they were added to the process heap, so when doing a minor garbage collection, the MSO sweeper only has to sweep until it encounters an off-heap binary that is on the old heap.

    Virtual Binary heap

    Each process has a virtual binary heap associated with it that has the size of all the current off-heap binaries that the process has references to. The virtual binary heap also has a limit and grows and shrinks depending on how off-heap binaries are used by the process. The same growth and shrink mechanisms are used for the binary heap and for the term heap, so first a Fibonacci like series and then 20% growth.

    The virtual binary heap exists in order to trigger garbage collections earlier when potentially there is a very large amount of off-heap binary data that could be reclaimed. This approach does not catch all problems with binary memory not being released soon enough, but it does catch a lot of them.

    Messages

    Messages can become a part of the process heap at different times. This depends on how the process is configured. +} else { + copy(ptr); +}

    The erts_is_literal check works differently on different architectures and operating systems.

    On 64 bit systems that allow mapping of unreserved virtual memory areas (most operating systems except Windows), an area of size 1 GB (by default) is mapped and then all literals are placed within that area. Then all that has to be done to determine if something is a literal or not is two quick pointer checks. This system relies on the fact that a memory page that has not been touched yet does not take any actual space. So even if 1 GB of virtual memory is mapped, only the memory which is actually needed for literals is allocated in ram. The size of the literal area is configurable through the +MIscs erts_alloc option.

    On 32 bit systems, there is not enough virtual memory space to allocate 1 GB for just literals, so instead small 256 KB sized literal regions are created on demand and a card mark bit-array of the entire 32 bit memory space is then used to determine if a term is a literal or not. Since the total memory space is only 32 bits, the card mark bit-array is only 256 words large. On a 64 bit system the same bit-array would have to be 1 tera words large, so this technique is only viable on 32 bit systems. Doing lookups in the array is a little more expensive then just doing the pointer checks that can be done in 64 bit systems, but not extremely so.

    On 64 bit windows, on which erts_alloc cannot do unreserved virtual memory mappings, a special tag within the Erlang term object is used to determine if something is a literal or not. This is very cheap, however, the tag is only available on 64 bit machines, and it is possible to do a great deal of other nice optimizations with this tag in the future (like for instance a more compact list implementation) so it is not used on operating systems where it is not needed.

    This behaviour is different from how it worked prior to Erlang/OTP 19.0. Before 19.0 the literal check was done by checking if the pointer pointed to the young or old heap block. If it did not, then it was considered a literal. This lead to considerable overhead and strange memory usage scenarios, so it was removed in 19.0.

    Binary heap

    The binary heap works as a large object space for binary terms that are greater than 64 bytes (from now on called off-heap binaries). The binary heap is reference counted and a pointer to the off-heap binary is stored on the process heap. To keep track of when to decrement the reference counter of the off-heap binary, a linked list (the MSO - mark and sweep object list) containing funs and externals as well as off-heap binaries is woven through the heap. After a garbage collection is done, the MSO list is swept and any off-heap binary that does not have a move marker written into the header words has its reference decremented and is potentially freed.

    All items in the MSO list are ordered by the time they were added to the process heap, so when doing a minor garbage collection, the MSO sweeper only has to sweep until it encounters an off-heap binary that is on the old heap.

    Virtual Binary heap

    Each process has a virtual binary heap associated with it that has the size of all the current off-heap binaries that the process has references to. The virtual binary heap also has a limit and grows and shrinks depending on how off-heap binaries are used by the process. The same growth and shrink mechanisms are used for the binary heap and for the term heap, so first a Fibonacci like series and then 20% growth.

    The virtual binary heap exists in order to trigger garbage collections earlier when potentially there is a very large amount of off-heap binary data that could be reclaimed. This approach does not catch all problems with binary memory not being released soon enough, but it does catch a lot of them.

    Messages

    Messages can become a part of the process heap at different times. This depends on how the process is configured. We can configure the behaviour of each process using process_flag(message_queue_data, off_heap | on_heap) or we can set a default for all processes at start using the option +hmqd.

    What do these different configurations do and when should we use them? Let's start by going through what happens when one Erlang process sends a message to another. The sending process needs to do a couple of things:

    1. calculate how large the message to be sent is
    2. allocate enough space to fit the entire message
    3. copy the message payload
    4. allocate a message container with some meta data
    5. insert the message container in the receiver process' message queue

    The process flag message_queue_data, of the receiver process, controls the message allocating strategy of the sender process in step 2 and also how the message data is treated by the garbage collector.

    The procedure above is different from how it worked prior to 19.0. Before 19.0 there was no configuration option, the behaviour was always very similar to how the on_heap option is in 19.0.

    Message allocating strategies

    If set to on_heap, the sending process will first attempt to allocate the space for the message directly on the young heap block of the receiving process. /usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/inet_cfg.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1174)) --- old//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/inet_cfg.html 2026-08-21 04:00:18.254287151 +0000 +++ new//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/inet_cfg.html 2026-08-21 04:00:18.254287151 +0000 @@ -117,11 +117,11 @@ The user configuration file is always examined last in the configuration process, making it possible for the user to override any default values or previously made settings. Call inet:get_rc() to view the state of the inet -configuration database.

    The valid configuration parameters are as follows:

    • {file, Format, File}.
      -  Format = atom()
      -  File = string()

      Specify a system file that Erlang is to read configuration data from. Format -tells the parser how the file is to be interpreted:

      • resolv (Unix resolv.conf)
      • host_conf_freebsd (FreeBSD host.conf)
      • host_conf_bsdos (BSDOS host.conf)
      • host_conf_linux (Linux host.conf)
      • nsswitch_conf (Unix nsswitch.conf)
      • hosts (Unix hosts)

      File is to specify the filename with full path.

    • {resolv_conf, File}.
      -  File = string()

      Specify a system file that Erlang is to read resolver configuration from for +configuration database.

      The valid configuration parameters are as follows:

      • {file, Format, File}.
        +  Format = atom()
        +  File = string()

        Specify a system file that Erlang is to read configuration data from. Format +tells the parser how the file is to be interpreted:

        • resolv (Unix resolv.conf)
        • host_conf_freebsd (FreeBSD host.conf)
        • host_conf_bsdos (BSDOS host.conf)
        • host_conf_linux (Linux host.conf)
        • nsswitch_conf (Unix nsswitch.conf)
        • hosts (Unix hosts)

        File is to specify the filename with full path.

      • {resolv_conf, File}.
        +  File = string()

        Specify a system file that Erlang is to read resolver configuration from for the internal DNS client inet_res, and monitor for changes, even if it does not exist. The path must be absolute.

        This can override the configuration parameters nameserver and search depending on the contents of the specified file. They can also change any time @@ -129,61 +129,61 @@ in the future. This emulates the old behavior of not configuring the DNS client when the node is started in short name distributed mode.

        If this parameter is not specified, it defaults to /etc/resolv.conf unless environment variable ERL_INET_ETC_DIR is set, which defines the directory -for this file to some maybe other than /etc.

      • {hosts_file, File}.
        -  File = string()

        Specify a system file that Erlang is to read resolver configuration from for +for this file to some maybe other than /etc.

      • {hosts_file, File}.
        +  File = string()

        Specify a system file that Erlang is to read resolver configuration from for the internal hosts file resolver, and monitor for changes, even if it does not exist. The path must be absolute.

        These host entries are searched after all added with {file, hosts, File} above or {host, IP, Aliases} below when lookup option file is used.

        If the file is specified as an empty string "", no file is read or monitored in the future. This emulates the old behavior of not configuring the DNS client when the node is started in short name distributed mode.

        If this parameter is not specified, it defaults to /etc/hosts unless environment variable ERL_INET_ETC_DIR is set, which defines the directory -for this file to some maybe other than /etc.

      • {registry, Type}.
        -  Type = atom()

        Specify a system registry that Erlang is to read configuration data from. -win32 is the only valid option.

      • {host, IP, Aliases}.
        -  IP = tuple()

        Aliases = [string()]

        Add host entry to the hosts table.

      • {domain, Domain}.
        -  Domain = string()

        Set domain name.

      • {nameserver, IP [,Port]}.
        -  IP = tuple()
        -  Port = integer()

        Add address (and port, if other than default) of the primary nameserver to use -for inet_res.

      • {alt_nameserver, IP [,Port]}.
        -  IP = tuple()
        -  Port = integer()

        Add address (and port, if other than default) of the secondary nameserver for -inet_res.

      • {search, Domains}.
        -  Domains = [string()]

        Add search domains for inet_res.

      • {lookup, Methods}.
        -  Methods = [atom()]

        Specify lookup methods and in which order to try them. The valid methods are +for this file to some maybe other than /etc.

      • {registry, Type}.
        +  Type = atom()

        Specify a system registry that Erlang is to read configuration data from. +win32 is the only valid option.

      • {host, IP, Aliases}.
        +  IP = tuple()

        Aliases = [string()]

        Add host entry to the hosts table.

      • {domain, Domain}.
        +  Domain = string()

        Set domain name.

      • {nameserver, IP [,Port]}.
        +  IP = tuple()
        +  Port = integer()

        Add address (and port, if other than default) of the primary nameserver to use +for inet_res.

      • {alt_nameserver, IP [,Port]}.
        +  IP = tuple()
        +  Port = integer()

        Add address (and port, if other than default) of the secondary nameserver for +inet_res.

      • {search, Domains}.
        +  Domains = [string()]

        Add search domains for inet_res.

      • {lookup, Methods}.
        +  Methods = [atom()]

        Specify lookup methods and in which order to try them. The valid methods are as follows:

        • native (use system calls)
        • file (use host data retrieved from system configuration files and/or the user configuration file)
        • dns (use the Erlang DNS client inet_res for nameserver queries)

        The lookup method string tries to parse the hostname as an IPv4 or IPv6 string and return the resulting IP address. It is automatically tried first when native is not in the Methods list. To skip it in this case, the pseudo lookup method nostring can be inserted anywhere in the Methods -list.

      • {cache_size, Size}.
        -  Size = integer()

        Set the resolver cache size for dns lookups. native lookups are not -cached. Defaults to 100 DNS records.

      • {cache_refresh, Time}.
        -  Time = integer()

        Set how often (in milliseconds) the resolver cache for inet_res is -refreshed (that is, expired DNS records are deleted). Defaults to 1 hour.

      • {timeout, Time}.
        -  Time = integer()

        Set the time to wait until retry (in milliseconds) for DNS queries made by -inet_res. Defaults to 2 seconds.

      • {retry, N}.
        -  N = integer()

        Set the number of DNS queries inet_res will try before giving up. Defaults -to 3.

      • {servfail_retry_timeout, Time}.
        -  Time = non_neg_integer()

        After all name servers have been tried, there is a timeout before the name +list.

      • {cache_size, Size}.
        +  Size = integer()

        Set the resolver cache size for dns lookups. native lookups are not +cached. Defaults to 100 DNS records.

      • {cache_refresh, Time}.
        +  Time = integer()

        Set how often (in milliseconds) the resolver cache for inet_res is +refreshed (that is, expired DNS records are deleted). Defaults to 1 hour.

      • {timeout, Time}.
        +  Time = integer()

        Set the time to wait until retry (in milliseconds) for DNS queries made by +inet_res. Defaults to 2 seconds.

      • {retry, N}.
        +  N = integer()

        Set the number of DNS queries inet_res will try before giving up. Defaults +to 3.

      • {servfail_retry_timeout, Time}.
        +  Time = non_neg_integer()

        After all name servers have been tried, there is a timeout before the name servers are tried again. This is to prevent the server from answering the query with what's in the servfail cache, inet_res. Defaults to 1500 milli -seconds .

      • {inet6, Bool}.
        +seconds .

      • {inet6, Bool}.
           Bool = true | false

        Tells the DNS client inet_res to look up IPv6 addresses. Defaults to -false.

      • {usevc, Bool}.
        +false.

      • {usevc, Bool}.
           Bool = true | false

        Tells the DNS client inet_res to use TCP (Virtual Circuit) instead of UDP. -Defaults to false.

      • {edns, Version}.
        +Defaults to false.

      • {edns, Version}.
           Version = false | 0

        Sets the EDNS version that inet_res will use. The only allowed version is -zero. Defaults to false, which means not to use EDNS.

      • {udp_payload_size, Size}.
        -  N = integer()

        Sets the allowed UDP payload size inet_res will advertise in EDNS queries. +zero. Defaults to false, which means not to use EDNS.

      • {udp_payload_size, Size}.
        +  N = integer()

        Sets the allowed UDP payload size inet_res will advertise in EDNS queries. Also sets the limit when the DNS query will be deemed too large for UDP forcing a TCP query instead; this is not entirely correct, as the advertised UDP payload size of the individual nameserver is what is to be used, but this simple strategy will do until a more intelligent (probing, caching) algorithm needs to be implemented. Default to 1280, which stems from the standard -Ethernet MTU size.

      • {udp, Module}.
        -  Module = atom()

        Tell Erlang to use another primitive UDP module than inet_udp.

      • {tcp, Module}.
        -  Module = atom()

        Tell Erlang to use another primitive TCP module than inet_tcp.

      • clear_hosts.

        Clear the hosts table.

      • clear_ns.

        Clear the list of recorded nameservers (primary and secondary).

      • clear_search.

        Clear the list of search domains.

      User Configuration Example

      Assume that a user does not want Erlang to use the native lookup method, but +Ethernet MTU size.

    • {udp, Module}.
      +  Module = atom()

      Tell Erlang to use another primitive UDP module than inet_udp.

    • {tcp, Module}.
      +  Module = atom()

      Tell Erlang to use another primitive TCP module than inet_tcp.

    • clear_hosts.

      Clear the hosts table.

    • clear_ns.

      Clear the list of recorded nameservers (primary and secondary).

    • clear_search.

      Clear the list of search domains.

    User Configuration Example

    Assume that a user does not want Erlang to use the native lookup method, but wants Erlang to read all information necessary from start and use that for resolving names and addresses. If lookup fails, Erlang is to request the data from a nameserver (using the Erlang DNS client, set to use EDNS allowing larger @@ -192,19 +192,19 @@ (in this example named erl_inetrc, stored in directory ./cfg_files) can then look as follows (Unix):

    %% -- ERLANG INET CONFIGURATION FILE --
     %% read the hosts file
    -{file, hosts, "/etc/hosts"}.
    +{file, hosts, "/etc/hosts"}.
     %% add a particular host
    -{host, {134,138,177,105}, ["finwe"]}.
    +{host, {134,138,177,105}, ["finwe"]}.
     %% do not monitor the hosts file
    -{hosts_file, ""}.
    +{hosts_file, ""}.
     %% read and monitor nameserver config from here
    -{resolv_conf, "/usr/local/etc/resolv.conf"}.
    +{resolv_conf, "/usr/local/etc/resolv.conf"}.
     %% enable EDNS
    -{edns,0}.
    +{edns,0}.
     %% disable caching
    -{cache_size, 0}.
    +{cache_size, 0}.
     %% specify lookup method
    -{lookup, [file, dns]}.

    And Erlang can, for example, be started as follows:

    % erl -sname my_node -kernel inetrc '"./cfg_files/erl_inetrc"'
    +{lookup, [file, dns]}.

    And Erlang can, for example, be started as follows:

    % erl -sname my_node -kernel inetrc '"./cfg_files/erl_inetrc"'
    /usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/init.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (906)) --- old//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/init.html 2026-08-21 04:00:18.275287288 +0000 +++ new//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/init.html 2026-08-21 04:00:18.275287288 +0000 @@ -120,8 +120,8 @@ initialization process.

  • -extra - Everything following -extra is considered plain arguments and can be retrieved using get_plain_arguments/0.

    Example:

    % erl -extra +A 1 --
     ...
    -1> init:get_plain_arguments().
    -["+A","1","--"]

    The -extra flag can be passed on the command line, through ERL_*FLAGS or +1> init:get_plain_arguments(). +["+A","1","--"]

  • The -extra flag can be passed on the command line, through ERL_*FLAGS or -args_file. It only effects the remaining command-line flags in the entity in which it is passed. If multiple -extra flags are passed they are concatenated using the same order rules as ERL_*FLAGS or -args_file in @@ -169,13 +169,13 @@ atoms.

    Example

    % erl -- a b -children thomas claire -ages 7 3 -- x y
     ...
     
    -1> init:get_plain_arguments().
    -["a","b","x","y"]
    -2> init:get_argument(children).
    -{ok,[["thomas","claire"]]}
    -3> init:get_argument(ages).
    -{ok, [["7","3"]]}
    -4> init:get_argument(silly).
    +1> init:get_plain_arguments().
    +["a","b","x","y"]
    +2> init:get_argument(children).
    +{ok,[["thomas","claire"]]}
    +3> init:get_argument(ages).
    +{ok, [["7","3"]]}
    +4> init:get_argument(silly).
     error

    See Also

    erl_prim_loader, heart

    @@ -471,12 +471,12 @@

    Returns all values associated with the command-line user flag Flag.

    If Flag is provided several times, each Values is returned in preserved order. Example:

    % erl -a b c -a d
     ...
    -1> init:get_argument(a).
    -{ok,[["b","c"],["d"]]}

    The following flags are defined automatically and can be retrieved using this +1> init:get_argument(a). +{ok,[["b","c"],["d"]]}

    The following flags are defined automatically and can be retrieved using this function:

    • root - The installation directory of Erlang/OTP, $ROOT:

      2> init:get_argument(root).
      -{ok,[["/usr/local/otp/releases/otp_beam_solaris8_r10b_patched"]]}
    • progname - The name of the program which started Erlang:

      3> init:get_argument(progname).
      -{ok,[["erl"]]}
    • home - The home directory (on Unix, the value of $HOME):

      4> init:get_argument(home).
      -{ok,[["/home/harry"]]}

    Returns error if no value is associated with Flag.

    +{ok,[["/usr/local/otp/releases/otp_beam_solaris8_r10b_patched"]]}
  • progname - The name of the program which started Erlang:

    3> init:get_argument(progname).
    +{ok,[["erl"]]}
  • home - The home directory (on Unix, the value of $HOME):

    4> init:get_argument(home).
    +{ok,[["/home/harry"]]}
  • Returns error if no value is associated with Flag.

    /usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/match_spec.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2412)) --- old//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/match_spec.html 2026-08-21 04:00:18.298287438 +0000 +++ new//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/match_spec.html 2026-08-21 04:00:18.298287438 +0000 @@ -281,64 +281,64 @@ matches or does not. The effect when the expression matches is a trace message rather than a returned term. The ActionTerms are executed as in an imperative language, that is, for their side effects. Functions with side effects are also -allowed when tracing.

    Tracing Examples

    Match an argument list of three, where the first and third arguments are equal:

    [{['$1', '_', '$1'],
    -  [],
    -  []}]

    Match an argument list of three, where the second argument is a number > 3:

    [{['_', '$1', '_'],
    -  [{ '>', '$1', 3}],
    -  []}]

    Match an argument list of three, where the third argument is either a tuple +allowed when tracing.

    Tracing Examples

    Match an argument list of three, where the first and third arguments are equal:

    [{['$1', '_', '$1'],
    +  [],
    +  []}]

    Match an argument list of three, where the second argument is a number > 3:

    [{['_', '$1', '_'],
    +  [{ '>', '$1', 3}],
    +  []}]

    Match an argument list of three, where the third argument is either a tuple containing argument one and two, or a list beginning with argument one and two -(that is, [a,b,[a,b,c]] or [a,b,{a,b}]):

    [{['$1', '$2', '$3'],
    -  [{'orelse',
    -      {'=:=', '$3', {{'$1','$2'}}},
    -      {'and',
    -        {'=:=', '$1', {hd, '$3'}},
    -        {'=:=', '$2', {hd, {tl, '$3'}}}}}],
    -  []}]

    The above problem can also be solved as follows:

    [{['$1', '$2', {'$1', '$2}], [], []},
    - {['$1', '$2', ['$1', '$2' | '_']], [], []}]

    Match two arguments, where the first is a tuple beginning with a list that in +(that is, [a,b,[a,b,c]] or [a,b,{a,b}]):

    [{['$1', '$2', '$3'],
    +  [{'orelse',
    +      {'=:=', '$3', {{'$1','$2'}}},
    +      {'and',
    +        {'=:=', '$1', {hd, '$3'}},
    +        {'=:=', '$2', {hd, {tl, '$3'}}}}}],
    +  []}]

    The above problem can also be solved as follows:

    [{['$1', '$2', {'$1', '$2}], [], []},
    + {['$1', '$2', ['$1', '$2' | '_']], [], []}]

    Match two arguments, where the first is a tuple beginning with a list that in turn begins with the second argument times two (that is, [{[4,x],y},2] or -[{[8], y, z},4]):

    [{['$1', '$2'],[{'=:=', {'*', 2, '$2'}, {hd, {element, 1, '$1'}}}],
    -  []}]

    Match three arguments. When all three are equal and are numbers, append the +[{[8], y, z},4]):

    [{['$1', '$2'],[{'=:=', {'*', 2, '$2'}, {hd, {element, 1, '$1'}}}],
    +  []}]

    Match three arguments. When all three are equal and are numbers, append the process dump to the trace message, otherwise let the trace message be "as is", -but set the sequential trace token label to 4711:

    [{['$1', '$1', '$1'],
    -  [{is_number, '$1'}],
    -  [{message, {process_dump}}]},
    - {'_', [], [{set_seq_token, label, 4711}]}]

    As can be noted above, the parameter list can be matched against a single +but set the sequential trace token label to 4711:

    [{['$1', '$1', '$1'],
    +  [{is_number, '$1'}],
    +  [{message, {process_dump}}]},
    + {'_', [], [{set_seq_token, label, 4711}]}]

    As can be noted above, the parameter list can be matched against a single MatchVariable or an '_'. To replace the whole parameter list with a single variable is a special case. In all other cases the MatchHead must be a -proper list.

    Generate a trace message only if the trace control word is set to 1:

    [{'_',
    -  [{'==',{get_tcw},{const, 1}}],
    -  []}]

    Generate a trace message only if there is a seq_trace token:

    [{'_',
    -  [{'==',{is_seq_trace},{const, 1}}],
    -  []}]

    Remove the 'silent' trace flag when the first argument is 'verbose', and add -it when it is 'silent':

    [{'$1',
    -  [{'==',{hd, '$1'},verbose}],
    -  [{trace, [silent],[]}]},
    - {'$1',
    -  [{'==',{hd, '$1'},silent}],
    -  [{trace, [],[silent]}]}]

    Add a return_trace message if the function is of arity 3:

    [{'$1',
    -  [{'==',{length, '$1'},3}],
    -  [{return_trace}]},
    - {'_',[],[]}]

    Generate a trace message only if the function is of arity 3 and the first -argument is 'trace':

    [{['trace','$2','$3'],
    -  [],
    -  []},
    - {'_',[],[]}]

    ETS Examples

    Match all objects in an ETS table, where the first element is the atom -'strider' and the tuple arity is 3, and return the whole object:

    [{{strider,'_','_'},
    -  [],
    -  ['$_']}]

    Match all objects in an ETS table with arity > 1 and the first element is -'gandalf', and return element 2:

    [{'$1',
    -  [{'==', gandalf, {element, 1, '$1'}},{'>=',{size, '$1'},2}],
    -  [{element,2,'$1'}]}]

    In this example, if the first element had been the key, it is much more +proper list.

    Generate a trace message only if the trace control word is set to 1:

    [{'_',
    +  [{'==',{get_tcw},{const, 1}}],
    +  []}]

    Generate a trace message only if there is a seq_trace token:

    [{'_',
    +  [{'==',{is_seq_trace},{const, 1}}],
    +  []}]

    Remove the 'silent' trace flag when the first argument is 'verbose', and add +it when it is 'silent':

    [{'$1',
    +  [{'==',{hd, '$1'},verbose}],
    +  [{trace, [silent],[]}]},
    + {'$1',
    +  [{'==',{hd, '$1'},silent}],
    +  [{trace, [],[silent]}]}]

    Add a return_trace message if the function is of arity 3:

    [{'$1',
    +  [{'==',{length, '$1'},3}],
    +  [{return_trace}]},
    + {'_',[],[]}]

    Generate a trace message only if the function is of arity 3 and the first +argument is 'trace':

    [{['trace','$2','$3'],
    +  [],
    +  []},
    + {'_',[],[]}]

    ETS Examples

    Match all objects in an ETS table, where the first element is the atom +'strider' and the tuple arity is 3, and return the whole object:

    [{{strider,'_','_'},
    +  [],
    +  ['$_']}]

    Match all objects in an ETS table with arity > 1 and the first element is +'gandalf', and return element 2:

    [{'$1',
    +  [{'==', gandalf, {element, 1, '$1'}},{'>=',{size, '$1'},2}],
    +  [{element,2,'$1'}]}]

    In this example, if the first element had been the key, it is much more efficient to match that key in the MatchHead part than in the MatchConditions part. The search space of the tables is restricted with regards to the MatchHead so that only objects with the matching key are searched.

    Match tuples of three elements, where the second element is either 'merry' or -'pippin', and return the whole objects:

    [{{'_',merry,'_'},
    -  [],
    -  ['$_']},
    - {{'_',pippin,'_'},
    -  [],
    -  ['$_']}]

    Function ets:test_ms/2 can be useful for testing complicated ETS matches.

    +'pippin', and return the whole objects:

    [{{'_',merry,'_'},
    +  [],
    +  ['$_']},
    + {{'_',pippin,'_'},
    +  [],
    +  ['$_']}]

    Function ets:test_ms/2 can be useful for testing complicated ETS matches.

    /usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (42505)) --- old//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/notes.html 2026-08-21 04:00:18.444288388 +0000 +++ new//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/notes.html 2026-08-21 04:00:18.446288401 +0000 @@ -90,27 +90,27 @@

    This document describes the changes made to the ERTS application.

    Erts 16.4.0.4

    Fixed Bugs and Malfunctions

    • Mitigated a denial of service attack in epmd.

      Thanks to Ryan Moore for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-20136 Aux Id: CVE-2026-42792, PR-11386

    • Fixed heap corruption when an invalidly encoded tuple with an arity of 2^31 or larger is decoded from Erlang's External Term Format (binary_to_term).

      Own Id: OTP-20214 Aux Id: PR-11297, CVE-2026-55737

    • When send_timeout is set and send_timeout_close is set to true, a 'tcp_closed' message is expected when the timeout occurs, but that (message) was not delivered. -This has now been fixed.

      Own Id: OTP-20257 Aux Id: GH-11319

    • A crafted External Term Format (ETF) payload could crash the runtime system.

      Thanks to Paul Guyot for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

      Own Id: OTP-20259 Aux Id: CVE-2026-54890, PR-11386

    • Fixed a rounding error in 16-bit float conversion.

      Own Id: OTP-20260 Aux Id: GH-11332, PR-11334

    Erts 16.4.0.3

    Fixed Bugs and Malfunctions

    • Fixed an undefined behavior in the internal erts_qsort() function, which could have been the cause of a beam crash seen when updating large maps.

      Own Id: OTP-20185 Aux Id: PR-11215

    • Calculating bxor of the largest supported positive integer (erlang:system_info(max_integer)) and -1 would return [] instead of a raising a system_limit exception.

      Own Id: OTP-20208 Aux Id: PR-11269

    • Fix possible race between ets:delete/1 and terminating process with a fixation on the same table.

      Own Id: OTP-20217 Aux Id: PR-11283

    • A few code generation issues for the JIT on AArch64 (ARM64) have been fixed.

      For all platforms, the loader will reject some invalid BEAM files earlier.

      Own Id: OTP-20226 Aux Id: PR-11299

    Improvements and New Features

    • Arithmetic operations on large integers will now increase the reduction count for the process, causing context switches to occur more frequently when doing arithmetic on large integers.

      Own Id: OTP-20211 Aux Id: PR-11274

    Erts 16.4.0.2

    Fixed Bugs and Malfunctions

    • Fixed bug in ets:member/2 for set, bag and duplicate_bag. The bug could (maybe) lead to ets:member spuriously returning false for a value which is actually a member for a table that faces high insert load.

      Own Id: OTP-20152 Aux Id: PR-11115

    • A buffer overflow error when parsing SCTP ERROR or ABORT chunks has been fixed.

      This could lead to stack corruption and VM crash, but ultimately with hard work by an attacker be refined into maybe even remote code execution.

      Own Id: OTP-20165 Aux Id: PR-1234, GHSA-6f4f-chj5-5g97, CVE-2026-49759

    Erts 16.4.0.1

    Fixed Bugs and Malfunctions

    • Fixed erlang:md5_init to always return the same deterministic context binary. Only an issue in OTP 28.5 when OTP was built with --disable-builtin-openssl or --enable-use-embedded-3pp-alternatives.

      Own Id: OTP-20123

    • Added explicit configure test for C++ function std::to_chars if options --disable-builtin-ryu or --enable-use-embedded-3pp-alternatives is used.

      Own Id: OTP-20126 Aux Id: PR-11067

    Erts 16.4

    Fixed Bugs and Malfunctions

    • Fixed bug in enif_make_map_from_arrays for arrays with at least 33 keys. If duplicate keys existed, instead of failing, it would skip the duplicates. If less than 33 unique keys existed, an internally inconsistent and broken map was returned.

      Own Id: OTP-20098 Aux Id: PR-10976

    • Fixed an issue when supplying the args_file option to erl.exe on windows that did not handle unicode characters correctly.

      Own Id: OTP-20101 Aux Id: GH-10667

    Improvements and New Features

    • A new configure option --{enable,disable}-use-embedded-3pp-alternatives has been added. When enabled, configure is forced to find alternatives, to a subset, of the embedded third-party products (3pps) in the runtime system, and when disabled, configure will use all internal embedded 3pps. Currently this option affects zstd, zlib, ryu (with STL), openssl and tcl. The default is to use all built-in embedded 3pps except for zlib which by default will use zlib on the OS if available.

      Requirements for alternatives:

      • zstd - Static library and include files of at least version 1.5.6 needs to be available.
      • zlib - Library and include files of at least version 1.2.5 needs to be available.
      • ryu (with STL) - A usable C++ compiler with C++17 support.
      • openssl - No requirements. Our own MD5 implementation will be used.
      • tcl - The strerrorname_np() function (introduced in glibc 2.32) mapping errno integers to symbolic names needs to be available.

      The argument embedded_3pps has been added to erlang:system_info/1. It returns a map with information about the use of embedded 3pps in the runtime system.

      Own Id: OTP-20106 Aux Id: PR-11045

    Erts 16.3.1

    Fixed Bugs and Malfunctions

    • Fixed a JIT bug that miscompiled expressions like X * X + X * X.

      Own Id: OTP-19889 Aux Id: GH-10454, PR-10456

    • Fixed bug on windows that made tools dialyzer, erlc and typer unusable in powershell or cmd.exe, when there are spaces in the installation path.

      Own Id: OTP-20027 Aux Id: PR-10620

    • Fixed a bug with prim_tty that could occur on windows if we cannot get the console mode, mark the TTY as unavailable. This can happen when the input handle is a pipe, but the output handle is a console.

      Own Id: OTP-20060 Aux Id: PR-10899

    Erts 16.3

    Fixed Bugs and Malfunctions

    • Fixed a documentation build warning when one or more applications failed their configure step and were skipped.

      Own Id: OTP-19914 Aux Id: ERIERL-1251,PR-10537

    • The (IPv6) flowinfo control message header was not properly supported.

      Own Id: OTP-19977

    • Fixed NetBSD thread naming, using pthread_setname_np(); used for debugging.

      Own Id: OTP-19987 Aux Id: PR-10684

    Improvements and New Features

    • The erlang:link_option/0 type is now exported.

      Own Id: OTP-19904 Aux Id: PR-10451

    • Added persistent_term:put_new/2 that will quickly do nothing if a term with the given name and value already exists, and raise a badarg exception if the term exists with a different value.

      Own Id: OTP-19908 Aux Id: GH-9681, PR-9695

    • The manifest.xml file for the Windows build now has version numbers updated to correctly report OS versions on Windows 10, 11, Server 2016, 2019, 2022.

      Own Id: OTP-19920 Aux Id: GH-10371, PR-10546

    • Improved yielding inside re:run. Regular expressions searching for one specific byte character could spin in memchr() without any yielding or reduction counting.

      Own Id: OTP-19950 Aux Id: PR-10486

    • Updated openssl from 3.6.0 to 3.6.1.

      This change does not perform any changes in the md5 vendor implementation from openssl. The change merges upstream cosmetic changes from openssl. This is necessary to automatically migrate cleanly to the next openssl version without conflicts with upstream.

      Own Id: OTP-19959 Aux Id: PR-10630

    • Updated ryu implementation used to convert floats to strings.

      Own Id: OTP-19974 Aux Id: PR-10672

    • Upgraded asmjit to v1.18

      Own Id: OTP-19979 Aux Id: PR-10675

    • Updated zlib to version 1.3.2.

      Own Id: OTP-19998 Aux Id: PR-10752

    Erts 16.2.2

    Fixed Bugs and Malfunctions

    • Fixed bug in erlang:monitor_node for rare reconnect race with multiple node monitoring from the same process.

      Own Id: OTP-19902 Aux Id: PR-10518

    • Add missing copyrights.

      Own Id: OTP-20008

    Erts 16.2.1

    Fixed Bugs and Malfunctions

    • Fail the windows build properly when nsis is not recognised.

      Own Id: OTP-19926 Aux Id: PR-10547

    • Socket accept cancel could cause fatal crash (core dump) on Windows.

      Own Id: OTP-19958

    • Fixed bug in ets:update_counter/4 and ets:update_element/4 accepting and inserting a default tuple smaller than the keypos of the table. Such a tuple without a key element would make the table internally inconsistent and might lead to bad behavior at table access, like ERTS runtime crash.

      Now a call to ets:update_counter/4 or ets:update_element/4 will fail with badarg if the key does not exist in the table and the default tuple is too small.

      Own Id: OTP-19962 Aux Id: PR-10616

    • A missing memory barrier when unlocking process locks could cause unexpected behavior on architectures with weak memory ordering such as for example ARM.

      Own Id: OTP-19978 Aux Id: PR-10664

    • A process could fail to wake from hibernation when a non‑message signal followed by a message signal arrived concurrently as the receiving process hibernated. If the process had a large heap, triggering a dirty GC, the wakeup could be lost.

      This bug existed since OTP 27.0.

      Own Id: OTP-19983 Aux Id: GH-10651, PR-10696

    Erts 16.2

    Fixed Bugs and Malfunctions

    • Fixed a build issue on modern compilers.

      Own Id: OTP-19789 Aux Id: PR-9983

    • When multiple processes called the same fun whose defining module was not loaded, a badfun exception could sometimes occur in one of the calling processes. This would only happen with the JIT runtime system.

      Own Id: OTP-19803 Aux Id: PR-10257

    • Fix a bug where Erlang/OTP tools could load a different boot script from CWD.

      Own Id: OTP-19819 Aux Id: PR-10317

    • Fixed a bug when more than one session traced the same BIF. Disabling tracing for a BIF in one session could incorrectly disable tracing of the BIF in other trace sessions as well.

      Own Id: OTP-19840 Aux Id: PR-10349

    • Fixed a slight performance regression in erlang:binary_to_term/1,2.

      Own Id: OTP-19859 Aux Id: PR-10383, GH-8329

    • Two socket related code warts found by PVS Studio has been fixed. One caused gen_tcp to no convert the send error econnaborted to econnreset on Windows. The other caused socket:sendfile/* to indicate the wrong error for a bad Offset.

      Own Id: OTP-19862 Aux Id: PR-10362, PR-10388

    • Fixed bug causing VM crash if an Erlang process gets killed while executing re:run with a (presumably) large subject string.

      Own Id: OTP-19888 Aux Id: GH-10432, PR-10439

    Improvements and New Features

    • Updated the vendor dependencies SHA to improve the accuracy of the source SBOM with purl pointing to the exact vendor commit that Erlang/OTP builds upon.

      Own Id: OTP-19777 Aux Id: PR-10216

    • Receive buffer allocation has been optimized for socket socket in that an underutilized buffers' content is copied to a freshly allocated binary of the right size instead of being reallocated.

      This optimization was already implemented for the socket:recv/1 functions, but now the same buffer stragegy is shared between all socket receive operations.

      Own Id: OTP-19794 Aux Id: PR-10231

    • Option(s) to create gen_tcp and socket sockets with protocol IPPROTO_MPTCP has been implemented.

      See functions gen_tcp:listen/2, gen_tcp:connect/4 and the type socket:protocol/0.

      Own Id: OTP-19814

    • erlc will now limit the number of ports and processes when starting erl in order to use less memory.

      Own Id: OTP-19852 Aux Id: PR-10364

    • Support for the socket options TCP_KEEPCNT, TCP_KEEPIDLE, and TCP_KEEPINTVL have been implemented for gen_tcp, as well as TCP_USER_TIMEOUT for both gen_tcp and socket.

      Own Id: OTP-19857 Aux Id: OTP-19814, PR-10390

    • Limit size of sctp_event_subscribe on Linux

      Own Id: OTP-19863 Aux Id: PR-10321

    • Updated MD5 implementation from OpenSSL 3.5.0 to 3.6.0

      Own Id: OTP-19870 Aux Id: PR-10405

    • Improved performance when doing socket:accept on the same socket from many processes on large multi core systems under high rate of connections. Mitigating performance regression seen since OTP 28.0.

      Own Id: OTP-19873 Aux Id: PR-10323, GH-10322

    • Updated STL version used.

      Own Id: OTP-19876

    • Updated PCRE2 to 10.47. Also picked newer fix, from upstream PCRE2, to bug that could cause benign random uninitialized data in exported regular expressions.

      Own Id: OTP-19880 Aux Id: PR-10391

    Erts 16.1.2

    Fixed Bugs and Malfunctions

    • Fixed a JIT bug that could miscompile equality tests on empty bitstrings.

      Own Id: OTP-19846 Aux Id: PR-10359

    • The documentation building code produced warnings during the build, if none of the applications were skipped. The warnings were resolved.

      Own Id: OTP-19865 Aux Id: ERIERL-1251,PR-10396

    Erts 16.1.1

    Fixed Bugs and Malfunctions

    • Fixed the erl documentation of the default timewarp mode used.

      Own Id: OTP-19790 Aux Id: PR-9970

    • The erlang:suspend_process() BIFs failed to suspend processes currently executing on dirty schedulers.

      Own Id: OTP-19799 Aux Id: PR-10241

    Erts 16.1

    Fixed Bugs and Malfunctions

    • Made sure to not set any terminal settings when they have not been changed. Doing so can trigger a SIGTTOU signal which would terminate Erlang when it should not.

      Own Id: OTP-19685 Aux Id: PR-9906

    • As an optimization, when the unicode:characters_to_binary/3 was used to convert from latin1 to utf8 or vice versa, it would return the original binary unchanged if it only contained 7-bit ASCII characters. That otpimization was broken in Erlang/OTP 27, and has now been mended.

      Own Id: OTP-19728 Aux Id: GH-10072, PR-10093

    Improvements and New Features

    • Fixed C compiler warnings generated by codechecker.

      Own Id: OTP-19671 Aux Id: PR-9832

    • Added support in module re for export and import of compiled regular expression in order to safely move them between Erlang node instances.

      Own Id: OTP-19730 Aux Id: PR-9976

    • Added new erl command line flag +Mumadtn <bool> causing MADV_DONTNEED to be passed to madvise() instead of MADV_FREE.

      Own Id: OTP-19739 Aux Id: PR-10113

    Erts 16.0.3

    Fixed Bugs and Malfunctions

    • Update PCRE2 from 10.45 to 10.46. Fixes potential buffer read overflow on regular expressions with (*scs:) and (*ACCEPT) syntax combined.

      Own Id: OTP-19755 Aux Id: CVE-2025-58050

    • Fixed bug that could cause crash in beam started with erl -emu_type debug +JPperf true with any type of tracing return from function.

      Own Id: OTP-19761 Aux Id: PR-19755

    Erts 16.0.2

    Fixed Bugs and Malfunctions

    • prim_net nif used incorrect encoding for family resulting in non-functional address selection.

      Own Id: OTP-19674

    • Fix windows uninstall command.

      Own Id: OTP-19683 Aux Id: PR-9887, GH-9992, GH-9884

    • With this change erlang will start if it receives short (ms-dos compatible) path to executable.

      Own Id: OTP-19690 Aux Id: PR-9996

    Improvements and New Features

    • The maximum amount of connections for epmd on Windows platforms has been increased from 64 to 1024.

      Own Id: OTP-19710 Aux Id: PR-10039

    Erts 16.0.1

    Fixed Bugs and Malfunctions

    • Fix Erlang to not crash when io:standard_error/0 is a terminal but io:standard_io/0 is not. This bug has existed since Erlang/OTP 28.0 and only effects Windows.

      Own Id: OTP-19650 Aux Id: GH-9872, PR-9878

    • In a debug build, the BIFs for the native debugger could cause a lock order violation diagnostic from the lock checker.

      Own Id: OTP-19665 Aux Id: PR-9926

    • When building ERTS make sure correct pcre2.h file is included even if CFLAGS contains extra include paths.

      Own Id: OTP-19675 Aux Id: PR-9892

    Erts 16.0

    Fixed Bugs and Malfunctions

    • ETS tables with more than 2 billion keys are now supported.

      Own Id: OTP-19144 Aux Id: PR-8589

    • The zlib library included in Erlang/OTP has been updated to version 1.3.1.

      Own Id: OTP-19259 Aux Id: PR-8862

    • to_erl no longer clears the screen when attaching to a run_erl session.

      Own Id: OTP-19263 Aux Id: PR-8943

    • The size of an atom in the Erlang source code was limited to 255 bytes in previous releases, meaning that an atom containing only emojis could contain only 63 emojis.

      While atoms are still only allowed to contain 255 characters, the number of bytes is no longer limited.

      External tools that parse the AtU8 chunk of a BEAM file directly need to be updated. Tools that use beam_lib:chunks(Beam, [atoms]) to read the atom table will continue to work.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19285 Aux Id: PR-8913

    • Fixed a bug where erlc would crash if its path contained spaces.

      Own Id: OTP-19295 Aux Id: PR-8937

    • The -noshell mode has been updated to read data lazily from standard input. Before this fix any data would be read greedily which meant that Erlang could consume data not meant for it. It also meant that in order for shell:start_interactive/0 to work on Windows an API that did not support reading of Unicode characters had to be used.

      Own Id: OTP-19313 Aux Id: PR-8962, GH-8113

    • The literals chunk in BEAM is no longer compressed, resulting in slightly smaller BEAM files when a BEAM file is stripped using beam_lib:strip_files/1.

      This is a potential incompatibility for tools that read and interpret the contents of the literal chunk. One way to update such tools to work with the new format is to retrieve the chunk using beam_lib:chunks(Beam, [literals]).

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19323 Aux Id: GH-8967, PR-8988

    • Fixed erlang:localtime_to_universaltime/2 with IsDST set to true and a timezone without daylight saving (for example UTC) to assume that the provided localtime does not have DST. This has always been the behaviour, but glibc versions after 2.37 changed it so that the behavior in Erlang also changed.

      Own Id: OTP-19453 Aux Id: PR-9207

    • Support for the TZ environment variable has been added on Windows. Before this change only the time zone configured in the OS was ever used.

      Own Id: OTP-19454 Aux Id: PR-9207

    • Suppressed various warnings when building the emulator with recent versions of GCC

      Own Id: OTP-19488 Aux Id: GH-9413, PR-9417

    • Fixed a bug in re:run and re:compile where the pattern parameter would be read incorrectly if it was a sub-binary.

      Own Id: OTP-19507 Aux Id: PR-9478, GH-9438

    • Fixed a broken makefile rule that made it so that O2 and -O2 could not be part of the directory path when building Erlang/OTP. Bug has been present since R11B released 2006.

      Own Id: OTP-19518 Aux Id: PR-9488, GH-9487

    • Fixed the index types of modules atomics and counters from integer() to pos_integer(), which is more correct.

      Own Id: OTP-19532 Aux Id: PR-9538

    • Fix erl flags +Q, +P and +t to not allow values greater than 4294975487. Before this fix, the runtime would either truncate the value or crash depending on which value was given.

      Own Id: OTP-19594 Aux Id: PR-9671, GH-9668

    • The socket option names for built-in socket options in the module socket has been cleaned up.

      Now, for known socket options, it is only the canonical protocol names that are allowed such as ip for the socket option {ip,recvtos}. Previously, due to being a protocol alias; {'IP',recvtos} was also allowed, as was the incorrect {hopopt,recvtos} because the protocol hopopt on Linux has the same protocol number as ip.

      So, to reduce confusion, all enumerated protocol names with the same number, are not allowed for the known protocol options, only the canonical name.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19615 Aux Id: PR-9718

    • On windows, socket:sendv could incorrectly return {ok, integer()} on Windows.

      Own Id: OTP-19617 Aux Id: OTP-19482

    Improvements and New Features

    • Functionality making it possible for processes to enable reception of priority messages has been introduced in accordance with EEP 76.

      Own Id: OTP-19198 Aux Id: PR-9269, PR-9519, PR-9590

    • The trace:system/3 function has been added. It has a similar interface as erlang:system_monitor/2 but it also supports trace sessions.

      Own Id: OTP-19271 Aux Id: PR-8660

    • Added support for SIGWINCH, SIGCONT, and SIGINFO signals to os:set_signal/2 where available.

      Own Id: OTP-19278 Aux Id: PR-8887, PR-8938

    • The erl -noshell mode has been updated to have two sub modes called raw and cooked, where cooked is the old default behaviour and raw can be used to bypass the line-editing support of the native terminal. Using raw mode it is possible to read keystrokes as they happen without the user having to press Enter. Also, the raw mode does not echo the typed characters to stdout. An example of how to create a tic-tac-toe game using this mechanism is included in the documentation.

      Own Id: OTP-19314 Aux Id: PR-8962, GH-8037

    • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

      All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

      -type meter() :: integer().
      --type foot() :: integer().

      Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

      -nominal meter() :: integer().
      --nominal foot() :: integer().

      More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

      Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

      Own Id: OTP-19364 Aux Id: PR-9079

    • Two BIFs have been added to the erlang module.

      erlang:processes_iterator/0 returns a process iterator that can be used to +This has now been fixed.

      Own Id: OTP-20257 Aux Id: GH-11319

    • A crafted External Term Format (ETF) payload could crash the runtime system.

      Thanks to Paul Guyot for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

      Own Id: OTP-20259 Aux Id: CVE-2026-54890, PR-11386

    • Fixed a rounding error in 16-bit float conversion.

      Own Id: OTP-20260 Aux Id: GH-11332, PR-11334

    Erts 16.4.0.3

    Fixed Bugs and Malfunctions

    • Fixed an undefined behavior in the internal erts_qsort() function, which could have been the cause of a beam crash seen when updating large maps.

      Own Id: OTP-20185 Aux Id: PR-11215

    • Calculating bxor of the largest supported positive integer (erlang:system_info(max_integer)) and -1 would return [] instead of a raising a system_limit exception.

      Own Id: OTP-20208 Aux Id: PR-11269

    • Fix possible race between ets:delete/1 and terminating process with a fixation on the same table.

      Own Id: OTP-20217 Aux Id: PR-11283

    • A few code generation issues for the JIT on AArch64 (ARM64) have been fixed.

      For all platforms, the loader will reject some invalid BEAM files earlier.

      Own Id: OTP-20226 Aux Id: PR-11299

    Improvements and New Features

    • Arithmetic operations on large integers will now increase the reduction count for the process, causing context switches to occur more frequently when doing arithmetic on large integers.

      Own Id: OTP-20211 Aux Id: PR-11274

    Erts 16.4.0.2

    Fixed Bugs and Malfunctions

    • Fixed bug in ets:member/2 for set, bag and duplicate_bag. The bug could (maybe) lead to ets:member spuriously returning false for a value which is actually a member for a table that faces high insert load.

      Own Id: OTP-20152 Aux Id: PR-11115

    • A buffer overflow error when parsing SCTP ERROR or ABORT chunks has been fixed.

      This could lead to stack corruption and VM crash, but ultimately with hard work by an attacker be refined into maybe even remote code execution.

      Own Id: OTP-20165 Aux Id: PR-1234, GHSA-6f4f-chj5-5g97, CVE-2026-49759

    Erts 16.4.0.1

    Fixed Bugs and Malfunctions

    • Fixed erlang:md5_init to always return the same deterministic context binary. Only an issue in OTP 28.5 when OTP was built with --disable-builtin-openssl or --enable-use-embedded-3pp-alternatives.

      Own Id: OTP-20123

    • Added explicit configure test for C++ function std::to_chars if options --disable-builtin-ryu or --enable-use-embedded-3pp-alternatives is used.

      Own Id: OTP-20126 Aux Id: PR-11067

    Erts 16.4

    Fixed Bugs and Malfunctions

    • Fixed bug in enif_make_map_from_arrays for arrays with at least 33 keys. If duplicate keys existed, instead of failing, it would skip the duplicates. If less than 33 unique keys existed, an internally inconsistent and broken map was returned.

      Own Id: OTP-20098 Aux Id: PR-10976

    • Fixed an issue when supplying the args_file option to erl.exe on windows that did not handle unicode characters correctly.

      Own Id: OTP-20101 Aux Id: GH-10667

    Improvements and New Features

    • A new configure option --{enable,disable}-use-embedded-3pp-alternatives has been added. When enabled, configure is forced to find alternatives, to a subset, of the embedded third-party products (3pps) in the runtime system, and when disabled, configure will use all internal embedded 3pps. Currently this option affects zstd, zlib, ryu (with STL), openssl and tcl. The default is to use all built-in embedded 3pps except for zlib which by default will use zlib on the OS if available.

      Requirements for alternatives:

      • zstd - Static library and include files of at least version 1.5.6 needs to be available.
      • zlib - Library and include files of at least version 1.2.5 needs to be available.
      • ryu (with STL) - A usable C++ compiler with C++17 support.
      • openssl - No requirements. Our own MD5 implementation will be used.
      • tcl - The strerrorname_np() function (introduced in glibc 2.32) mapping errno integers to symbolic names needs to be available.

      The argument embedded_3pps has been added to erlang:system_info/1. It returns a map with information about the use of embedded 3pps in the runtime system.

      Own Id: OTP-20106 Aux Id: PR-11045

    Erts 16.3.1

    Fixed Bugs and Malfunctions

    • Fixed a JIT bug that miscompiled expressions like X * X + X * X.

      Own Id: OTP-19889 Aux Id: GH-10454, PR-10456

    • Fixed bug on windows that made tools dialyzer, erlc and typer unusable in powershell or cmd.exe, when there are spaces in the installation path.

      Own Id: OTP-20027 Aux Id: PR-10620

    • Fixed a bug with prim_tty that could occur on windows if we cannot get the console mode, mark the TTY as unavailable. This can happen when the input handle is a pipe, but the output handle is a console.

      Own Id: OTP-20060 Aux Id: PR-10899

    Erts 16.3

    Fixed Bugs and Malfunctions

    • Fixed a documentation build warning when one or more applications failed their configure step and were skipped.

      Own Id: OTP-19914 Aux Id: ERIERL-1251,PR-10537

    • The (IPv6) flowinfo control message header was not properly supported.

      Own Id: OTP-19977

    • Fixed NetBSD thread naming, using pthread_setname_np(); used for debugging.

      Own Id: OTP-19987 Aux Id: PR-10684

    Improvements and New Features

    • The erlang:link_option/0 type is now exported.

      Own Id: OTP-19904 Aux Id: PR-10451

    • Added persistent_term:put_new/2 that will quickly do nothing if a term with the given name and value already exists, and raise a badarg exception if the term exists with a different value.

      Own Id: OTP-19908 Aux Id: GH-9681, PR-9695

    • The manifest.xml file for the Windows build now has version numbers updated to correctly report OS versions on Windows 10, 11, Server 2016, 2019, 2022.

      Own Id: OTP-19920 Aux Id: GH-10371, PR-10546

    • Improved yielding inside re:run. Regular expressions searching for one specific byte character could spin in memchr() without any yielding or reduction counting.

      Own Id: OTP-19950 Aux Id: PR-10486

    • Updated openssl from 3.6.0 to 3.6.1.

      This change does not perform any changes in the md5 vendor implementation from openssl. The change merges upstream cosmetic changes from openssl. This is necessary to automatically migrate cleanly to the next openssl version without conflicts with upstream.

      Own Id: OTP-19959 Aux Id: PR-10630

    • Updated ryu implementation used to convert floats to strings.

      Own Id: OTP-19974 Aux Id: PR-10672

    • Upgraded asmjit to v1.18

      Own Id: OTP-19979 Aux Id: PR-10675

    • Updated zlib to version 1.3.2.

      Own Id: OTP-19998 Aux Id: PR-10752

    Erts 16.2.2

    Fixed Bugs and Malfunctions

    • Fixed bug in erlang:monitor_node for rare reconnect race with multiple node monitoring from the same process.

      Own Id: OTP-19902 Aux Id: PR-10518

    • Add missing copyrights.

      Own Id: OTP-20008

    Erts 16.2.1

    Fixed Bugs and Malfunctions

    • Fail the windows build properly when nsis is not recognised.

      Own Id: OTP-19926 Aux Id: PR-10547

    • Socket accept cancel could cause fatal crash (core dump) on Windows.

      Own Id: OTP-19958

    • Fixed bug in ets:update_counter/4 and ets:update_element/4 accepting and inserting a default tuple smaller than the keypos of the table. Such a tuple without a key element would make the table internally inconsistent and might lead to bad behavior at table access, like ERTS runtime crash.

      Now a call to ets:update_counter/4 or ets:update_element/4 will fail with badarg if the key does not exist in the table and the default tuple is too small.

      Own Id: OTP-19962 Aux Id: PR-10616

    • A missing memory barrier when unlocking process locks could cause unexpected behavior on architectures with weak memory ordering such as for example ARM.

      Own Id: OTP-19978 Aux Id: PR-10664

    • A process could fail to wake from hibernation when a non‑message signal followed by a message signal arrived concurrently as the receiving process hibernated. If the process had a large heap, triggering a dirty GC, the wakeup could be lost.

      This bug existed since OTP 27.0.

      Own Id: OTP-19983 Aux Id: GH-10651, PR-10696

    Erts 16.2

    Fixed Bugs and Malfunctions

    • Fixed a build issue on modern compilers.

      Own Id: OTP-19789 Aux Id: PR-9983

    • When multiple processes called the same fun whose defining module was not loaded, a badfun exception could sometimes occur in one of the calling processes. This would only happen with the JIT runtime system.

      Own Id: OTP-19803 Aux Id: PR-10257

    • Fix a bug where Erlang/OTP tools could load a different boot script from CWD.

      Own Id: OTP-19819 Aux Id: PR-10317

    • Fixed a bug when more than one session traced the same BIF. Disabling tracing for a BIF in one session could incorrectly disable tracing of the BIF in other trace sessions as well.

      Own Id: OTP-19840 Aux Id: PR-10349

    • Fixed a slight performance regression in erlang:binary_to_term/1,2.

      Own Id: OTP-19859 Aux Id: PR-10383, GH-8329

    • Two socket related code warts found by PVS Studio has been fixed. One caused gen_tcp to no convert the send error econnaborted to econnreset on Windows. The other caused socket:sendfile/* to indicate the wrong error for a bad Offset.

      Own Id: OTP-19862 Aux Id: PR-10362, PR-10388

    • Fixed bug causing VM crash if an Erlang process gets killed while executing re:run with a (presumably) large subject string.

      Own Id: OTP-19888 Aux Id: GH-10432, PR-10439

    Improvements and New Features

    • Updated the vendor dependencies SHA to improve the accuracy of the source SBOM with purl pointing to the exact vendor commit that Erlang/OTP builds upon.

      Own Id: OTP-19777 Aux Id: PR-10216

    • Receive buffer allocation has been optimized for socket socket in that an underutilized buffers' content is copied to a freshly allocated binary of the right size instead of being reallocated.

      This optimization was already implemented for the socket:recv/1 functions, but now the same buffer stragegy is shared between all socket receive operations.

      Own Id: OTP-19794 Aux Id: PR-10231

    • Option(s) to create gen_tcp and socket sockets with protocol IPPROTO_MPTCP has been implemented.

      See functions gen_tcp:listen/2, gen_tcp:connect/4 and the type socket:protocol/0.

      Own Id: OTP-19814

    • erlc will now limit the number of ports and processes when starting erl in order to use less memory.

      Own Id: OTP-19852 Aux Id: PR-10364

    • Support for the socket options TCP_KEEPCNT, TCP_KEEPIDLE, and TCP_KEEPINTVL have been implemented for gen_tcp, as well as TCP_USER_TIMEOUT for both gen_tcp and socket.

      Own Id: OTP-19857 Aux Id: OTP-19814, PR-10390

    • Limit size of sctp_event_subscribe on Linux

      Own Id: OTP-19863 Aux Id: PR-10321

    • Updated MD5 implementation from OpenSSL 3.5.0 to 3.6.0

      Own Id: OTP-19870 Aux Id: PR-10405

    • Improved performance when doing socket:accept on the same socket from many processes on large multi core systems under high rate of connections. Mitigating performance regression seen since OTP 28.0.

      Own Id: OTP-19873 Aux Id: PR-10323, GH-10322

    • Updated STL version used.

      Own Id: OTP-19876

    • Updated PCRE2 to 10.47. Also picked newer fix, from upstream PCRE2, to bug that could cause benign random uninitialized data in exported regular expressions.

      Own Id: OTP-19880 Aux Id: PR-10391

    Erts 16.1.2

    Fixed Bugs and Malfunctions

    • Fixed a JIT bug that could miscompile equality tests on empty bitstrings.

      Own Id: OTP-19846 Aux Id: PR-10359

    • The documentation building code produced warnings during the build, if none of the applications were skipped. The warnings were resolved.

      Own Id: OTP-19865 Aux Id: ERIERL-1251,PR-10396

    Erts 16.1.1

    Fixed Bugs and Malfunctions

    • Fixed the erl documentation of the default timewarp mode used.

      Own Id: OTP-19790 Aux Id: PR-9970

    • The erlang:suspend_process() BIFs failed to suspend processes currently executing on dirty schedulers.

      Own Id: OTP-19799 Aux Id: PR-10241

    Erts 16.1

    Fixed Bugs and Malfunctions

    • Made sure to not set any terminal settings when they have not been changed. Doing so can trigger a SIGTTOU signal which would terminate Erlang when it should not.

      Own Id: OTP-19685 Aux Id: PR-9906

    • As an optimization, when the unicode:characters_to_binary/3 was used to convert from latin1 to utf8 or vice versa, it would return the original binary unchanged if it only contained 7-bit ASCII characters. That otpimization was broken in Erlang/OTP 27, and has now been mended.

      Own Id: OTP-19728 Aux Id: GH-10072, PR-10093

    Improvements and New Features

    • Fixed C compiler warnings generated by codechecker.

      Own Id: OTP-19671 Aux Id: PR-9832

    • Added support in module re for export and import of compiled regular expression in order to safely move them between Erlang node instances.

      Own Id: OTP-19730 Aux Id: PR-9976

    • Added new erl command line flag +Mumadtn <bool> causing MADV_DONTNEED to be passed to madvise() instead of MADV_FREE.

      Own Id: OTP-19739 Aux Id: PR-10113

    Erts 16.0.3

    Fixed Bugs and Malfunctions

    • Update PCRE2 from 10.45 to 10.46. Fixes potential buffer read overflow on regular expressions with (*scs:) and (*ACCEPT) syntax combined.

      Own Id: OTP-19755 Aux Id: CVE-2025-58050

    • Fixed bug that could cause crash in beam started with erl -emu_type debug +JPperf true with any type of tracing return from function.

      Own Id: OTP-19761 Aux Id: PR-19755

    Erts 16.0.2

    Fixed Bugs and Malfunctions

    • prim_net nif used incorrect encoding for family resulting in non-functional address selection.

      Own Id: OTP-19674

    • Fix windows uninstall command.

      Own Id: OTP-19683 Aux Id: PR-9887, GH-9992, GH-9884

    • With this change erlang will start if it receives short (ms-dos compatible) path to executable.

      Own Id: OTP-19690 Aux Id: PR-9996

    Improvements and New Features

    • The maximum amount of connections for epmd on Windows platforms has been increased from 64 to 1024.

      Own Id: OTP-19710 Aux Id: PR-10039

    Erts 16.0.1

    Fixed Bugs and Malfunctions

    • Fix Erlang to not crash when io:standard_error/0 is a terminal but io:standard_io/0 is not. This bug has existed since Erlang/OTP 28.0 and only effects Windows.

      Own Id: OTP-19650 Aux Id: GH-9872, PR-9878

    • In a debug build, the BIFs for the native debugger could cause a lock order violation diagnostic from the lock checker.

      Own Id: OTP-19665 Aux Id: PR-9926

    • When building ERTS make sure correct pcre2.h file is included even if CFLAGS contains extra include paths.

      Own Id: OTP-19675 Aux Id: PR-9892

    Erts 16.0

    Fixed Bugs and Malfunctions

    • ETS tables with more than 2 billion keys are now supported.

      Own Id: OTP-19144 Aux Id: PR-8589

    • The zlib library included in Erlang/OTP has been updated to version 1.3.1.

      Own Id: OTP-19259 Aux Id: PR-8862

    • to_erl no longer clears the screen when attaching to a run_erl session.

      Own Id: OTP-19263 Aux Id: PR-8943

    • The size of an atom in the Erlang source code was limited to 255 bytes in previous releases, meaning that an atom containing only emojis could contain only 63 emojis.

      While atoms are still only allowed to contain 255 characters, the number of bytes is no longer limited.

      External tools that parse the AtU8 chunk of a BEAM file directly need to be updated. Tools that use beam_lib:chunks(Beam, [atoms]) to read the atom table will continue to work.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19285 Aux Id: PR-8913

    • Fixed a bug where erlc would crash if its path contained spaces.

      Own Id: OTP-19295 Aux Id: PR-8937

    • The -noshell mode has been updated to read data lazily from standard input. Before this fix any data would be read greedily which meant that Erlang could consume data not meant for it. It also meant that in order for shell:start_interactive/0 to work on Windows an API that did not support reading of Unicode characters had to be used.

      Own Id: OTP-19313 Aux Id: PR-8962, GH-8113

    • The literals chunk in BEAM is no longer compressed, resulting in slightly smaller BEAM files when a BEAM file is stripped using beam_lib:strip_files/1.

      This is a potential incompatibility for tools that read and interpret the contents of the literal chunk. One way to update such tools to work with the new format is to retrieve the chunk using beam_lib:chunks(Beam, [literals]).

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19323 Aux Id: GH-8967, PR-8988

    • Fixed erlang:localtime_to_universaltime/2 with IsDST set to true and a timezone without daylight saving (for example UTC) to assume that the provided localtime does not have DST. This has always been the behaviour, but glibc versions after 2.37 changed it so that the behavior in Erlang also changed.

      Own Id: OTP-19453 Aux Id: PR-9207

    • Support for the TZ environment variable has been added on Windows. Before this change only the time zone configured in the OS was ever used.

      Own Id: OTP-19454 Aux Id: PR-9207

    • Suppressed various warnings when building the emulator with recent versions of GCC

      Own Id: OTP-19488 Aux Id: GH-9413, PR-9417

    • Fixed a bug in re:run and re:compile where the pattern parameter would be read incorrectly if it was a sub-binary.

      Own Id: OTP-19507 Aux Id: PR-9478, GH-9438

    • Fixed a broken makefile rule that made it so that O2 and -O2 could not be part of the directory path when building Erlang/OTP. Bug has been present since R11B released 2006.

      Own Id: OTP-19518 Aux Id: PR-9488, GH-9487

    • Fixed the index types of modules atomics and counters from integer() to pos_integer(), which is more correct.

      Own Id: OTP-19532 Aux Id: PR-9538

    • Fix erl flags +Q, +P and +t to not allow values greater than 4294975487. Before this fix, the runtime would either truncate the value or crash depending on which value was given.

      Own Id: OTP-19594 Aux Id: PR-9671, GH-9668

    • The socket option names for built-in socket options in the module socket has been cleaned up.

      Now, for known socket options, it is only the canonical protocol names that are allowed such as ip for the socket option {ip,recvtos}. Previously, due to being a protocol alias; {'IP',recvtos} was also allowed, as was the incorrect {hopopt,recvtos} because the protocol hopopt on Linux has the same protocol number as ip.

      So, to reduce confusion, all enumerated protocol names with the same number, are not allowed for the known protocol options, only the canonical name.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19615 Aux Id: PR-9718

    • On windows, socket:sendv could incorrectly return {ok, integer()} on Windows.

      Own Id: OTP-19617 Aux Id: OTP-19482

    Improvements and New Features

    • Functionality making it possible for processes to enable reception of priority messages has been introduced in accordance with EEP 76.

      Own Id: OTP-19198 Aux Id: PR-9269, PR-9519, PR-9590

    • The trace:system/3 function has been added. It has a similar interface as erlang:system_monitor/2 but it also supports trace sessions.

      Own Id: OTP-19271 Aux Id: PR-8660

    • Added support for SIGWINCH, SIGCONT, and SIGINFO signals to os:set_signal/2 where available.

      Own Id: OTP-19278 Aux Id: PR-8887, PR-8938

    • The erl -noshell mode has been updated to have two sub modes called raw and cooked, where cooked is the old default behaviour and raw can be used to bypass the line-editing support of the native terminal. Using raw mode it is possible to read keystrokes as they happen without the user having to press Enter. Also, the raw mode does not echo the typed characters to stdout. An example of how to create a tic-tac-toe game using this mechanism is included in the documentation.

      Own Id: OTP-19314 Aux Id: PR-8962, GH-8037

    • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

      All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

      -type meter() :: integer().
      +-type foot() :: integer().

      Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

      -nominal meter() :: integer().
      +-nominal foot() :: integer().

      More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

      Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

      Own Id: OTP-19364 Aux Id: PR-9079

    • Two BIFs have been added to the erlang module.

      erlang:processes_iterator/0 returns a process iterator that can be used to iterate through the process table.

      erlang:process_next/1 takes in a process iterator and returns a 2-tuple, consisting of a process identifier and a new process iterator. When the process iterator runs out of processes in the process table, none will be returned.

      Using these BIFs to scan the processes scales better than using erlang:processes/0, at the cost of giving less consistency guarantees. Process identifiers returned from consecutive calls of erlang:process_next/1 may not be a consistent snapshot of all elements existing in the table during any of the calls. A process identifier is only guaranteed to be returned from a call to erlang:processes_next/1 if it was alive before the call to erlang:processes_iterator/0 and was still alive when erlang:processes_next/1 returned none.

      Own Id: OTP-19369 Aux Id: PR-9129

    • Improved open debug for gen_tcp_socket (connect and listen) and gen_udp_socket (open).

      Own Id: OTP-19386

    • Module re has been updated to use PCRE2, which is mostly backward compatible with PCRE.

      The most noticeable incompatibilities are

      • The default character encoding is pure ASCII and not Latin1. Unicode support is still available with options unicode and ucp.
      • Options bsr_anycrlf, bsr_unicode and {newline,_} are only set when a regex is compiled and cannot be changed at matching for precompiled regex.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19431 Aux Id: PR-9299, PR-9610

    • When booting the runtime system on a 32-bit computer with a single core, the boot code will try to minimize the peak memory use by disabling parallel loading of BEAM files.

      Own Id: OTP-19450 Aux Id: PR-9342

    • A socket option {otp,select_read} has been added that enables keeping a socket in the VM select/poll set between calls to recv functions.

      This increases throughput by reducing the number of calls to said functions.

      Own Id: OTP-19451 Aux Id: PR-9344

    • erlc will now write compiler warnings and errors to standard error, instead of standard output, in common with other language compilers.

      Own Id: OTP-19460 Aux Id: GH-9255, PR-9363

    • Fixed the Windows build to always include .pdb files for all DLLs and executables to help with debugging.

      Own Id: OTP-19465 Aux Id: PR-9229

    • Improve the naming of the (internal) esock mutex(es). It is now possible to configure (as in autoconf) the use of simple names for the esock mutex(es).

      Own Id: OTP-19472 Aux Id: PR-9388

    • An optimization for appending 0 bits to a binary was removed in patch releases for OTP versions 25, 26, and 27. This optimization has been reintroduced in Erlang/OTP 28.

      Own Id: OTP-19473 Aux Id: PR-9396, PR-8697

    • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

      Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

    • When using enif_select_read (or enif_select with ERL_NIF_SELECT_READ) on systems with kernel polling enabled (that is most Unix systems), file descriptors that are always re-enabled as soon as they trigger are now part of a specialized pollset just as driver_select. This reduces the CPU usage in such scenarios as the erts does not have to re-insert the FD everytime it it triggered. As a result of this optimization socket based reading uses a lot less CPU and achieves a higher throughput.

      Own Id: OTP-19479 Aux Id: PR-9275

    • Added support for compiling Erlang/OTP for Windows on ARM64.

      Own Id: OTP-19480 Aux Id: PR-8734

    • The Windows installer no longer creates the erl.ini file, making installations redistributable.

      Own Id: OTP-19481 Aux Id: PR-9330

    • Added erlang:hibernate/0, which hibernates a process without discarding the stack.

      Own Id: OTP-19503 Aux Id: PR-9406

    • The asmjit library (used by BeamJIT) has been updated to version 029075b84bf0161a761beb63e6eda519a29020db.

      Own Id: OTP-19509 Aux Id: PR-9495

    • When compiling C/C++ code on Unix systems, the compiler hardening flags suggested by the Open Source Security Foundation are now enabled by default. To disable them, pass --disable-security-hardening-flags to configure.

      Own Id: OTP-19519 Aux Id: PR-9441

    • If a process being suspended using erlang:suspend_process() currently is waiting in a receive ... after expression, the timer for the timeout will now also be suspended until the process is resumed.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19536 Aux Id: PR-8670

    • A test module for TLS distribution over socket has been implemented.

      Own Id: OTP-19539 Aux Id: PR-9511

    • Upgrade pcre2 to 10.45

      Own Id: OTP-19541 Aux Id: PR-9582

    • The +R emulator options has been removed. It has had any effect since Erlang/OTP R9.

      Own Id: OTP-19551 Aux Id: PR-9608

    • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

      Own Id: OTP-19575 Aux Id: PR-9670

    • Increase the default inet-driver buffer size(s). Also introduce kernel parameters for UDP and SCTP to change the sizes when creating (those) sockets.

      Own Id: OTP-19576

    • Add +JPperfdirectory <dir> for specifying which directory Erlang should place perf symbol information files.

      Own Id: OTP-19589 Aux Id: PR-9639, GH-9500

    • Allow multiple static nifs to be part of the same archive. See the NIF documentation for details.

      Own Id: OTP-19590 Aux Id: PR-9625

    • Various improvements reducing lock contention on run queues due to task stealing.

      Own Id: OTP-19591 Aux Id: PR-9594

    • The new implementation has the same behavior as the previous one. The newer compilers already have native support for FP16, so this implementation is only relevant for older compilers. For this reason, the new implementation has not been tested for speed.

      Own Id: OTP-19603 Aux Id: PR-9735

    • An experimental API for a native debugger has been added. The main components are the following:

      • A new compiler option beam_debug_info for the Erlang compiler. When given, most optimizations are disabled and debug information suitable for the native debugger are added to generated BEAM files.

      • A new +D emulator flag. When given, the VM becomes "debuggable", which means that when modules that been compiled with the beam_debug_info option are loaded, the code is instrumented so that one can enable and disable breakpoints on executable lines.

      • An experimental erl_debugger module with a new debugging API. Essentially, it allows a single, local, process to be registered as the "debugger" process for the node. This process is the one that will receive messages notifying that a process hit a breakpoint. This way, the front-end implementation of a debugger (such as edb from WhatApp) can be decoupled from OTP.

      • The erl_debugger module also exposes new BIFs to inspect X and Y registers of a suspended process. Together with new code-information BIFs, this let's a debugger show the values of variables in scope for a suspended process.

      Own Id: OTP-19609 Aux Id: PR-8670, PR-9334, PR-9604

    • Update internal ryu implementation to use latest version. The new version is a little bit faster in some scenarios. ryu is used by float_to_list/1 and similar functions to convert floats to strings.

      Own Id: OTP-19613 Aux Id: PR-9733

    • Update of MD5 implementation from OpenSSL version 3.1.4 to 3.5.

      Own Id: OTP-19614 Aux Id: PR-9775

    • Small optimization in binary_to_term by not allocating an unnecessary large native stack frame.

      Own Id: OTP-19618 Aux Id: PR-9759, PR-9809

    Erts 15.2.7.8

    Fixed Bugs and Malfunctions

    • Fixed bug in enif_make_map_from_arrays for arrays with at least 33 keys. If duplicate keys existed, instead of failing, it would skip the duplicates. If less than 33 unique keys existed, an internally inconsistent and broken map was returned.

      Own Id: OTP-20098 Aux Id: PR-10976

    • Fixed an issue when supplying the args_file option to erl.exe on windows that did not handle unicode characters correctly.

      Own Id: OTP-20101 Aux Id: GH-10667

    Erts 15.2.7.7

    Fixed Bugs and Malfunctions

    • Fixed a JIT bug that miscompiled expressions like X * X + X * X.

      Own Id: OTP-19889 Aux Id: GH-10454, PR-10456

    • Fixed bug on windows that made tools dialyzer, erlc and typer unusable in powershell or cmd.exe, when there are spaces in the installation path.

      Own Id: OTP-20027 Aux Id: PR-10620

    Erts 15.2.7.6

    Fixed Bugs and Malfunctions

    • Fixed bug in ets:update_counter/4 and ets:update_element/4 accepting and inserting a default tuple smaller than the keypos of the table. Such a tuple without a key element would make the table internally inconsistent and might lead to bad behavior at table access, like ERTS runtime crash.

      Now a call to ets:update_counter/4 or ets:update_element/4 will fail with badarg if the key does not exist in the table and the default tuple is too small.

      Own Id: OTP-19962 Aux Id: PR-10616

    • A missing memory barrier when unlocking process locks could cause unexpected behavior on architectures with weak memory ordering such as for example ARM.

      Own Id: OTP-19978 Aux Id: PR-10664

    • A process could fail to wake from hibernation when a non‑message signal followed by a message signal arrived concurrently as the receiving process hibernated. If the process had a large heap, triggering a dirty GC, the wakeup could be lost.

      This bug existed since OTP 27.0.

      Own Id: OTP-19983 Aux Id: GH-10651, PR-10696

    Erts 15.2.7.5

    Fixed Bugs and Malfunctions

    • Fixed a JIT bug that could miscompile equality tests on empty bitstrings.

      Own Id: OTP-19846 Aux Id: PR-10359

    • Fail the windows build properly when nsis is not recognised.

      Own Id: OTP-19926 Aux Id: PR-10547

    Erts 15.2.7.4

    Improvements and New Features

    Erts 15.2.7.3

    Fixed Bugs and Malfunctions

    • Fixed the erl documentation of the default timewarp mode used.

      Own Id: OTP-19790 Aux Id: PR-9970

    • The erlang:suspend_process() BIFs failed to suspend processes currently executing on dirty schedulers.

      Own Id: OTP-19799 Aux Id: PR-10241

    • When multiple processes called the same fun whose defining module was not loaded, a badfun exception could sometimes occur in one of the calling processes. This would only happen with the JIT runtime system.

      Own Id: OTP-19803 Aux Id: PR-10257

    Erts 15.2.7.2

    Fixed Bugs and Malfunctions

    • As an optimization, when the unicode:characters_to_binary/3 was used to convert from latin1 to utf8 or vice versa, it would return the original binary unchanged if it only contained 7-bit ASCII characters. That otpimization was broken in Erlang/OTP 27, and has now been mended.

      Own Id: OTP-19728 Aux Id: GH-10072, PR-10093

    Erts 15.2.7.1

    Fixed Bugs and Malfunctions

    Improvements and New Features

    • The maximum amount of connections for epmd on Windows platforms has been increased from 64 to 1024.

      Own Id: OTP-19710 Aux Id: PR-10039

    Erts 15.2.7

    Fixed Bugs and Malfunctions

    • Fixed an emulator crash when setting an error_handler module that was not yet loaded.

      Own Id: OTP-19577 Aux Id: ERIERL-1220, PR-9696

    • Fixed a rare bug that could cause an emulator crash after unloading a module or erasing a persistent_term.

      Own Id: OTP-19599 Aux Id: PR-9724

    Erts 15.2.6

    Fixed Bugs and Malfunctions

    • Fixed bug in call_memory tracing that could cause wildly incorrect reported memory values. Bug exists since OTP 27.1.

      Also fixed return type spec of trace:info/3.

      Own Id: OTP-19581 Aux Id: ERIERL-1219, PR-9706

    Erts 15.2.5

    Fixed Bugs and Malfunctions

    • On Windows, using socket:sendv, a large IOV (size > MAX), the tail was not sent.

      Own Id: OTP-19482

    • Uplift pcre 8.44 to pcre 8.45

      Own Id: OTP-19565

    Erts 15.2.4

    Fixed Bugs and Malfunctions

    Erts 15.2.3

    Fixed Bugs and Malfunctions

    • Fixed failed runtime assert in debug VM when built with statically linked NIFs.

      Own Id: OTP-19443 Aux Id: GH-9306, PR-9307

    • Fixed a bug where reading a binary from persistent_term could cause a segmentation fault on Windows. This bug was introduced in Erlang/OTP 27.0.

      Own Id: OTP-19458 Aux Id: PR-9349, GH-9222

    • Fixed a crash in erlexec (an executable used by erl during startup) when a PATH longer than 10240 was set.

      Own Id: OTP-19471 Aux Id: PR-9331

    • Fixed bug in erlang:halt. Two processes calling erlang:halt at the same time could lead to one of them crashing with badarg as if it called erlang:halt(undefined,undefined).

      Own Id: OTP-19490 Aux Id: PR-8640, GH-8634

    • Fixed BEAM crash when a custom thread sends a large map (>128 keys) externally encoded with, for example, erl_drv_send_term().

      Own Id: OTP-19495 Aux Id: GH-8208, PR-8209

    Erts 15.2.2

    Fixed Bugs and Malfunctions

    • Disabled an unsafe runtime optimization in binary construction that caused silent memory corruption.

      Own Id: OTP-19462 Aux Id: ERIERL-1177, PR-9372

    Erts 15.2.1

    Fixed Bugs and Malfunctions

    • Fixed configure tests for GCC 14

      Own Id: OTP-19407 Aux Id: GH-9211, PR-9234

    • Fix bug where log printouts would go missing when application_controller is stopping while log messages are being sent.

      This bug was introduced by OTP-19078 in Erlang/OTP 26.2.5.

      Own Id: OTP-19418 Aux Id: GH-9163, PR-9274

    Erts 15.2

    Fixed Bugs and Malfunctions

    • gen_sctp:peeloff/2 has been fixed to inherit socket options to the peeled off socket more like gen_tcp:accept/1, for example the options tos or tclass.

      When setting SCTP options that are unsupported on the platform, some should be silently ignored, but a bug caused the option parsing to derail so the options after could bail out and cause an error instead. This has been fixed.

      Own Id: OTP-19225 Aux Id: PR-8789

    • Fixed a bug where Erlang would corrupt the terminal settings if stdin was a TTY but stdout was not.

      Own Id: OTP-19232 Aux Id: PR-8794, GH-8487

    • Fixed a bug in the non-JIT VM when loading a NIF over a function that is already traced by more than one session. This caused a VM crash. This bug has existed since OTP-27.0, where multiple trace sessions were introduced.

      Own Id: OTP-19248 Aux Id: PR-8856

    • Fixed a bug where the loading of modules with extremely large binary construction instructions crashed the emulator on AArch64.

      Own Id: OTP-19261 Aux Id: GH-8815, PR-8816

    • inet:getifaddrs/0,1 is improved when using -inet_backend = socket.

      Own Id: OTP-19264

    • win32reg:value/2 will no longer crash the emulator when the value is an unterminated REG_SZ of size 0.

      Own Id: OTP-19283 Aux Id: GH-8903, PR-8912

    • Makefile dependency generation on Windows in WSL 2 has been corrected.

      Own Id: OTP-19300 Aux Id: PR-8955

    • Fix lock order violation if a NIF monitor down callback calls enif_whereis_pid. Would cause debug emulator to crash but could potentially lead to deadlocks in optimized emulator.

      Own Id: OTP-19330 Aux Id: GH-8983, PR-9008

    • Fixed compilation faults when compiling using --enable-vm-probes.

      Own Id: OTP-19333

    • Fixed erl_nif.h on Windows to compile when gcc or clang is used.

      Own Id: OTP-19341 Aux Id: PR-9016

    • Fixed a minor issue in the JIT debug information that confused tools like GDB and perf.

      Own Id: OTP-19362 Aux Id: PR-9003

    Improvements and New Features

    • Improved documentation of timers.

      Own Id: OTP-19360 Aux Id: ERIERL-1149, PR-9062

    • The label for a process can now be retrieved also using process_info(Pid, label) in addition to proc_lib:get_label/1.

      This new option is useful when one wants to retrieve more than one process info item. For example:

      process_info(Pid, [label,registered_name])

      Own Id: OTP-19373 Aux Id: PR-9108

    Erts 15.1.3

    Fixed Bugs and Malfunctions

    • gen_udp:send on domain local can leak inet_reply messages.

      Own Id: OTP-19332 Aux Id: #href_anchor"erts-15-1-2" class="section-heading">Erts 15.1.2

      Fixed Bugs and Malfunctions

      • A bug has been fixed where receiving an SCTP message with gen_sctp could waste the first fragments of a message and only deliver the last fragment.

        This happened with low probability when the OS signaled that the socket was ready for reading in combination with an internal time-out retry.

        A bug has been fixed with a lingering time-out from after an SCTP connect that could stop the flow of incoming messages on an active gen_tcp socket.

        Own Id: OTP-19235 Aux Id: ERIERL-1133, PR-8837

      • An boolean option non_block_send for SCTP, has ben added to be able to achieve the old behaviour to avoid blocking send operations by passing the OS network stack error message ({error,eagain} through.

        Own Id: OTP-19258 Aux Id: OTP-19061, ERIERL-1134

      • The call gen_tcp:send/2 could hang indefinitely despite having set the send_timeout option for the following unfortunate combination of circumstances:

        • The socket has to be in passive mode.
        • All output buffers had to be filled util the high_watermark was hit, causing the gen_tcp:send/2 operation to block.
        • While the send operation was blocked, a gen_tcp:recv/2,3 call had to be done from a different process. It had to block, waiting for data for a while before completing the operation, and the received packet had to fill at least 75% of the receive buffer.

        Under these circumstances he information that a send operation was waiting got lost, so the send operation that blocked in the first placed would never return. The data it had would be sent, though, and send operations from other processes, still work.

        This bug has been fixed.

        Own Id: OTP-19267 Aux Id: GH-6455, OTP-18520, ERIERL-1138, PR-8892

      • In rare circumstances, in code that matches multiple tuples, the JIT could generate code that would raise a badmatch exception even if the given tuples were correct.

        Own Id: OTP-19268 Aux Id: GH-8875, PR-8895

      • Fixed beam crash that could happen if resetting call_time or call_memory trace counters of a function while it is called. Bug exists since OTP R16.

        Own Id: OTP-19269 Aux Id: GH-8835, PR-8897

      Erts 15.1.1

      Fixed Bugs and Malfunctions

      Erts 15.1

      Fixed Bugs and Malfunctions

      • The erl -man example has been corrected to not consider values set in ERL_ZFLAGS and stop parsing arguments when a -- is encountered.

        Own Id: OTP-19098 Aux Id: PR-8478, GH-8477

      • Compiler warnings for Windows I/O back-end have been silenced.

        Own Id: OTP-19113

      • Bugs related to return_to trace have been fixed. It did not work for more than once trace session and it did sometimes not trigger for exceptions.

        Own Id: OTP-19122

      • Potential deadlocks while writing a crash dump have been eliminated.

        Own Id: OTP-19133 Aux Id: PR-8521, GH-8498

      • When loading a damaged or too old BEAM file, the runtime system could crash.

        Own Id: OTP-19153 Aux Id: PR-8623

      • A scheduler thread could get stuck when deleting a memory allocator carrier when adjacent carriers were deleted and/or inserted simultaneously by other schedulers. This in turn could cause the other schedulers to get stuck as well.

        Own Id: OTP-19154 Aux Id: GH-8613, PR-8627

      • Statistics for number of carriers in a shared pool after calling instrument:allocations or instrument:carriers are now correct. Also, a potential bug in carrier block scanning was eliminated.

        Own Id: OTP-19166 Aux Id: PR-8636

      • A race in the kTLS flavour of SSL distribution has been fixed so that inet_drv.c doesn't read ahead too much data, which could cause the kTLS encryption to be activated too late when some encrypted data had already been read into the inet_drv.c buffer as unencrypted.

        Own Id: OTP-19175 Aux Id: GH-8561, PR-8690

      • Fixed an emulator crash relating to compressed ETS tables.

        Own Id: OTP-19176 Aux Id: PR-8683

      • A function (encode_sockaddr) was called with superfluous argument, on Windows, in the net nif.

        Own Id: OTP-19181

      • Fixed a crash that could happen on reallocation failure.

        Own Id: OTP-19192

      • Man pages are now available for erl, erlc, dialyzer, and all other programs that are included in Erlang/OTP.

        Own Id: OTP-19201 Aux Id: PR-8740

      • A previous correction in the Erlang/OTP 27.0.1 emergency patch had the unfortunate side effect of sometimes causing an unnecessary fullsweep (major) garbage collection instead of a generation (minor) garbage collection. This has been corrected.

        Own Id: OTP-19209 Aux Id: PR-8751, PR-8539

      • Fixed trace matchspec functions trace and enable_trace to use the session tracer when enabling trace flags on untraced processes.

        Own Id: OTP-19211 Aux Id: GH-8657

      • Fixed a typo in the type spec for erlang:garbage_collection_defaults/0.

        Own Id: OTP-19215 Aux Id: PR-8757

      • Corrected socket:ioctl for genaddr (SIOCGENADDR).

        Own Id: OTP-19216

      • The support for Transparent Huge Pages has been disabled on non-amd64 Linux systems.

        Own Id: OTP-19219 Aux Id: PR-8702

      • Fixed a race condition on Windows when upgrading from -noshell to a shell that would cause Erlang to crash with the error:

        {&#href_anchor"p">,
        -  'The I/O operation has been aborted because of either a thread exit or an application request.'}.

        Own Id: OTP-19220 Aux Id: PR-8774, GH-7621

      Improvements and New Features

      • Added functions getservbyname and getservbyport to the net module.

        Own Id: OTP-19101 Aux Id: OTP-18835

      • Introduced enet | esock variants of inet functions, either when called with sockets, -with explicit inet_backend config or with the e inet_backend kernel config option.

        Own Id: OTP-19132 Aux Id: OTP-19101

      • Optimize process and port creation when such tracing is not enabled by any trace session.

        Own Id: OTP-19167 Aux Id: PR-8655

      • Compiler warnings for some removed functions have been corrected to point out the correct replacement functions.

        Own Id: OTP-19186 Aux Id: PR-8709

      • A boolean option read_ahead has been implemented for gen_tcp, default true, to facilitate not reading past (caching data) the end of a packet. In particular, for kTLS, caching data could read in data that was supposed to be decrypted by the platform's network stack, before crypto parameters could be activated.

        Own Id: OTP-19199 Aux Id: OTP-19175, GH-8561, GH-8690, GH-8785

      • The zip module has been updated with support for:

        • zip64 archives - Archives larger than 4GB or with more than 2^32 entries.
        • extended timestamps - Higher resolution and in UTC.
        • UID/GID - Save and extract the original UID/GID.
        • Fixes so that permission mode attributes are correctly read and set for files in archives.
        • zip:list_dir/2 now also returns directories, not only files. (You can disable this behaviour by using the option skip_directories).

        Various bugs in the original implementation have also been fixed, such as:

        • Correctly encode and decode the DOS timestamps for entries within an archive (that is the non-extended timestamp).
        • Fix DOS timestamps to be set to localtime instead of UTC (use extended timestamps for UTC timestamps).
        • Use the unix file attributes read from disk when creating archives instead of setting everything to 644.

        Own Id: OTP-19214 Aux Id: PR-8765

      Erts 15.0.1

      Fixed Bugs and Malfunctions

      • In rare circumstances the JIT could do an unsafe in-place update of a tuple.

        Own Id: OTP-19108 Aux Id: PR-8539

      • When a port command crashed in the inet driver during gen_tcp:send/2, a monitor 'DOWN' message could be left lingering in the caller's mailbox. This has now been fixed.

        Own Id: OTP-19121 Aux Id: GH-8484

      • 'DOWN' messages originating from a monitored port, contained the atom process instead of the atom port as the third element when the exit reason was not an immediate term.

        Own Id: OTP-19123 Aux Id: GH-8484, PR-8546

      • Fix so that the options to enable Transparent Huge Page alignment of the Erlang VM executable are only applied to the Erlang VM and not other native programs such as erlc and dialyzer. This bug was introduced in Erlang/OTP 27.0.

        Own Id: OTP-19137 Aux Id: GH-8574

      • When no time warp mode was enabled, a smaller Erlang monotonic time could be read than a previously read time, i.e., breaking the monotonic property. The runtime system will abort when detecting an issue like this since OTP 24.3.4.17 and OTP 25.0.

        Up until OTP 25 no time warp mode is the default. As of OTP 26 multi time warp mode is the default.

        Own Id: OTP-19147 Aux Id: ERIERL-1043, ERIERL-1106, PR-8619

      • When calling trace:function(Session, _, true, [meta]) the meta tracer was incorrectly set to be the calling process. Now it's set to the session tracer as expected.

        Own Id: OTP-19151 Aux Id: PR-8616, GH-8614

      Erts 15.0

      Fixed Bugs and Malfunctions

      • Bugs in how erl -extra interacts with passing flags via ERL_*FLAGS or -args_file have been fixed.

        Own Id: OTP-18766 Aux Id: PR-7639

      • Fixed a bug that prevented the emulator from building on recent versions of Yocto Linux.

        Own Id: OTP-18918 Aux Id: PR-7952

      • Fixed spectre mitigation configure test to work with GCC patches to always add -fcf-protection=full.

        Own Id: OTP-18928 Aux Id: PR-8006

      • A call to socket:[recv|recvfrom|recvmsg]/* with Timeout = 0 on Windows could cause a (case clause) crash if data is immediately available.

        Own Id: OTP-19063 Aux Id: OTP-18835

      • Fix bug on Windows where exit_status would not be sent when a port exits after the stdin/stdout handles have been closed.

        Own Id: OTP-19077 Aux Id: PR-8324

      Improvements and New Features

      • Refactored how the JIT handles POSIX signals and how they affect thread stacks, allowing us to use the native stack register for Erlang stacks on more platforms.

        Notably, containers built on 64-bit x86 Alpine Linux images will now perform much better in sequential code. As an example, running dialyzer over the OTP code base finishes about 15% quicker.

        Own Id: OTP-18568 Aux Id: PR-7174

      • The instrument module can now track allocations on a per-process or per-port basis.

        Own Id: OTP-18577 Aux Id: PR-7236

      • The pid field returned from erlang:fun_info/1,2 is now always the pid for the init process of the local node, not the pid for the actual process that created the fun.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-18594 Aux Id: PR-7274

      • By default, escripts will now be compiled instead of interpreted. That means that the compiler application must be installed.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-18639 Aux Id: PR-7348

      • A binary returned from the socket receive functions is no longer created as a sub binary of an often large receive buffer binary (socket option {otp,rcvbuf}). This avoids space waste, trusting the allocators to implement reallocation efficiently.

        Own Id: OTP-18642 Aux Id: GH-6152, PR-7465

      • The default process limit has been raised to 1048576 processes.

        Own Id: OTP-18699 Aux Id: PR-7388

      • The erlang:system_monitor/2 functionality is now able to monitor long message queues in the system.

        Own Id: OTP-18709 Aux Id: PR-7651

      • The erl command now supports the -S flag, which is similar to the -run flag, except that it will pass all arguments up to end of the command line to the called function. (The -run flag will not pass arguments beginning with a hyphen.) Another difference is that -S will always call a function with one argument, passing an empty list if no arguments were given.

        Own Id: OTP-18744 Aux Id: PR-7470

      • When implementing an alternative carrier for the Erlang distribution, a separate input handler process may now be registered, using erlang:dist_ctrl_input_handler/2, also in the case when the distribution controller is a port.

        Own Id: OTP-18774 Aux Id: PR-7110

      • The call stack trace has now been added to the error reported by erlang:process_flag/2 when max_heap_size limit has been exceeded.

        Own Id: OTP-18779 Aux Id: PR-7592

      • -callback attributes have been added to erl_tracer.

        Own Id: OTP-18794 Aux Id: PR-7703

      • For inet_backend = socket, setting the active socket option alone, to once, true or N has been optimized, as well as the corresponding data delivery.

        Own Id: OTP-18835

      • New functions socket:sendv/* for sending I/O vectors have been added.

        Own Id: OTP-18845

      • Socket options that take string now also accept binaries.

        Own Id: OTP-18849 Aux Id: PR-6510

      • Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code.

        There are also new APIs to support native coverage without using the cover tool.

        To instrument code for native coverage it must be compiled with the line_coverage option.

        To enable native coverage in the runtime system, start it like so:

        $ erl +JPcover true

        There are also the following new functions for supporting native coverage:

        Own Id: OTP-18856 Aux Id: PR-7856

      • Changed the default value of the command line flag -code_path_choice to strict.

        Note that for application systems using archives, it is necessary to add the code_path_choice relaxed to the command line that invokes erl.

        Own Id: OTP-18894 Aux Id: PR-7243

      • Added module loading to erl -init_debug printouts.

        Own Id: OTP-18929 Aux Id: PR-8004

      • When the runtime system halts, it performs various flush operations before terminating. By default there is no limit on how much time the flush operations are allowed to take. A new halt flush timeout functionality has been introduced which can be used for limiting the amount of time that the flushing operations are allowed to take. For more information see the documentation of the flush_timeout option of the erlang:halt/2 BIF and the documentation of the erl +zhft <Timeout> command line flag.

        Own Id: OTP-18938 Aux Id: PR-8035, GH-7438

      • Optimized code loading by moving certain operations from the code server to the caller.

        Own Id: OTP-18941 Aux Id: PR-7981

      • Updated asmjit to version a465fe71ab3d0e224b2b4bd0fac69ae68ab9239d

        Own Id: OTP-18942

      • The deprecated functions in zlib have been removed. That includes inflateChunk/{1,2}, getBufSize/1, setBufSize/2, the CRC32 functions, and the Adler checksum functions.

        Own Id: OTP-18950

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      • Safe destructive update of tuples has been implemented in the compiler and runtime system. This allows the VM to update tuples in-place when it is safe to do so, thus improving performance by doing less copying but also by producing less garbage.

        Example:

        -record(rec, {a,b,c}).
        +inet_backend = socket.

        Own Id: OTP-19264

      • win32reg:value/2 will no longer crash the emulator when the value is an unterminated REG_SZ of size 0.

        Own Id: OTP-19283 Aux Id: GH-8903, PR-8912

      • Makefile dependency generation on Windows in WSL 2 has been corrected.

        Own Id: OTP-19300 Aux Id: PR-8955

      • Fix lock order violation if a NIF monitor down callback calls enif_whereis_pid. Would cause debug emulator to crash but could potentially lead to deadlocks in optimized emulator.

        Own Id: OTP-19330 Aux Id: GH-8983, PR-9008

      • Fixed compilation faults when compiling using --enable-vm-probes.

        Own Id: OTP-19333

      • Fixed erl_nif.h on Windows to compile when gcc or clang is used.

        Own Id: OTP-19341 Aux Id: PR-9016

      • Fixed a minor issue in the JIT debug information that confused tools like GDB and perf.

        Own Id: OTP-19362 Aux Id: PR-9003

      Improvements and New Features

      • Improved documentation of timers.

        Own Id: OTP-19360 Aux Id: ERIERL-1149, PR-9062

      • The label for a process can now be retrieved also using process_info(Pid, label) in addition to proc_lib:get_label/1.

        This new option is useful when one wants to retrieve more than one process info item. For example:

        process_info(Pid, [label,registered_name])

        Own Id: OTP-19373 Aux Id: PR-9108

      Erts 15.1.3

      Fixed Bugs and Malfunctions

      • gen_udp:send on domain local can leak inet_reply messages.

        Own Id: OTP-19332 Aux Id: #href_anchor"erts-15-1-2" class="section-heading">Erts 15.1.2

        Fixed Bugs and Malfunctions

        • A bug has been fixed where receiving an SCTP message with gen_sctp could waste the first fragments of a message and only deliver the last fragment.

          This happened with low probability when the OS signaled that the socket was ready for reading in combination with an internal time-out retry.

          A bug has been fixed with a lingering time-out from after an SCTP connect that could stop the flow of incoming messages on an active gen_tcp socket.

          Own Id: OTP-19235 Aux Id: ERIERL-1133, PR-8837

        • An boolean option non_block_send for SCTP, has ben added to be able to achieve the old behaviour to avoid blocking send operations by passing the OS network stack error message ({error,eagain} through.

          Own Id: OTP-19258 Aux Id: OTP-19061, ERIERL-1134

        • The call gen_tcp:send/2 could hang indefinitely despite having set the send_timeout option for the following unfortunate combination of circumstances:

          • The socket has to be in passive mode.
          • All output buffers had to be filled util the high_watermark was hit, causing the gen_tcp:send/2 operation to block.
          • While the send operation was blocked, a gen_tcp:recv/2,3 call had to be done from a different process. It had to block, waiting for data for a while before completing the operation, and the received packet had to fill at least 75% of the receive buffer.

          Under these circumstances he information that a send operation was waiting got lost, so the send operation that blocked in the first placed would never return. The data it had would be sent, though, and send operations from other processes, still work.

          This bug has been fixed.

          Own Id: OTP-19267 Aux Id: GH-6455, OTP-18520, ERIERL-1138, PR-8892

        • In rare circumstances, in code that matches multiple tuples, the JIT could generate code that would raise a badmatch exception even if the given tuples were correct.

          Own Id: OTP-19268 Aux Id: GH-8875, PR-8895

        • Fixed beam crash that could happen if resetting call_time or call_memory trace counters of a function while it is called. Bug exists since OTP R16.

          Own Id: OTP-19269 Aux Id: GH-8835, PR-8897

        Erts 15.1.1

        Fixed Bugs and Malfunctions

        Erts 15.1

        Fixed Bugs and Malfunctions

        • The erl -man example has been corrected to not consider values set in ERL_ZFLAGS and stop parsing arguments when a -- is encountered.

          Own Id: OTP-19098 Aux Id: PR-8478, GH-8477

        • Compiler warnings for Windows I/O back-end have been silenced.

          Own Id: OTP-19113

        • Bugs related to return_to trace have been fixed. It did not work for more than once trace session and it did sometimes not trigger for exceptions.

          Own Id: OTP-19122

        • Potential deadlocks while writing a crash dump have been eliminated.

          Own Id: OTP-19133 Aux Id: PR-8521, GH-8498

        • When loading a damaged or too old BEAM file, the runtime system could crash.

          Own Id: OTP-19153 Aux Id: PR-8623

        • A scheduler thread could get stuck when deleting a memory allocator carrier when adjacent carriers were deleted and/or inserted simultaneously by other schedulers. This in turn could cause the other schedulers to get stuck as well.

          Own Id: OTP-19154 Aux Id: GH-8613, PR-8627

        • Statistics for number of carriers in a shared pool after calling instrument:allocations or instrument:carriers are now correct. Also, a potential bug in carrier block scanning was eliminated.

          Own Id: OTP-19166 Aux Id: PR-8636

        • A race in the kTLS flavour of SSL distribution has been fixed so that inet_drv.c doesn't read ahead too much data, which could cause the kTLS encryption to be activated too late when some encrypted data had already been read into the inet_drv.c buffer as unencrypted.

          Own Id: OTP-19175 Aux Id: GH-8561, PR-8690

        • Fixed an emulator crash relating to compressed ETS tables.

          Own Id: OTP-19176 Aux Id: PR-8683

        • A function (encode_sockaddr) was called with superfluous argument, on Windows, in the net nif.

          Own Id: OTP-19181

        • Fixed a crash that could happen on reallocation failure.

          Own Id: OTP-19192

        • Man pages are now available for erl, erlc, dialyzer, and all other programs that are included in Erlang/OTP.

          Own Id: OTP-19201 Aux Id: PR-8740

        • A previous correction in the Erlang/OTP 27.0.1 emergency patch had the unfortunate side effect of sometimes causing an unnecessary fullsweep (major) garbage collection instead of a generation (minor) garbage collection. This has been corrected.

          Own Id: OTP-19209 Aux Id: PR-8751, PR-8539

        • Fixed trace matchspec functions trace and enable_trace to use the session tracer when enabling trace flags on untraced processes.

          Own Id: OTP-19211 Aux Id: GH-8657

        • Fixed a typo in the type spec for erlang:garbage_collection_defaults/0.

          Own Id: OTP-19215 Aux Id: PR-8757

        • Corrected socket:ioctl for genaddr (SIOCGENADDR).

          Own Id: OTP-19216

        • The support for Transparent Huge Pages has been disabled on non-amd64 Linux systems.

          Own Id: OTP-19219 Aux Id: PR-8702

        • Fixed a race condition on Windows when upgrading from -noshell to a shell that would cause Erlang to crash with the error:

          {&#href_anchor"p">,
          +  'The I/O operation has been aborted because of either a thread exit or an application request.'}.

          Own Id: OTP-19220 Aux Id: PR-8774, GH-7621

        Improvements and New Features

        • Added functions getservbyname and getservbyport to the net module.

          Own Id: OTP-19101 Aux Id: OTP-18835

        • Introduced enet | esock variants of inet functions, either when called with sockets, +with explicit inet_backend config or with the e inet_backend kernel config option.

          Own Id: OTP-19132 Aux Id: OTP-19101

        • Optimize process and port creation when such tracing is not enabled by any trace session.

          Own Id: OTP-19167 Aux Id: PR-8655

        • Compiler warnings for some removed functions have been corrected to point out the correct replacement functions.

          Own Id: OTP-19186 Aux Id: PR-8709

        • A boolean option read_ahead has been implemented for gen_tcp, default true, to facilitate not reading past (caching data) the end of a packet. In particular, for kTLS, caching data could read in data that was supposed to be decrypted by the platform's network stack, before crypto parameters could be activated.

          Own Id: OTP-19199 Aux Id: OTP-19175, GH-8561, GH-8690, GH-8785

        • The zip module has been updated with support for:

          • zip64 archives - Archives larger than 4GB or with more than 2^32 entries.
          • extended timestamps - Higher resolution and in UTC.
          • UID/GID - Save and extract the original UID/GID.
          • Fixes so that permission mode attributes are correctly read and set for files in archives.
          • zip:list_dir/2 now also returns directories, not only files. (You can disable this behaviour by using the option skip_directories).

          Various bugs in the original implementation have also been fixed, such as:

          • Correctly encode and decode the DOS timestamps for entries within an archive (that is the non-extended timestamp).
          • Fix DOS timestamps to be set to localtime instead of UTC (use extended timestamps for UTC timestamps).
          • Use the unix file attributes read from disk when creating archives instead of setting everything to 644.

          Own Id: OTP-19214 Aux Id: PR-8765

        Erts 15.0.1

        Fixed Bugs and Malfunctions

        • In rare circumstances the JIT could do an unsafe in-place update of a tuple.

          Own Id: OTP-19108 Aux Id: PR-8539

        • When a port command crashed in the inet driver during gen_tcp:send/2, a monitor 'DOWN' message could be left lingering in the caller's mailbox. This has now been fixed.

          Own Id: OTP-19121 Aux Id: GH-8484

        • 'DOWN' messages originating from a monitored port, contained the atom process instead of the atom port as the third element when the exit reason was not an immediate term.

          Own Id: OTP-19123 Aux Id: GH-8484, PR-8546

        • Fix so that the options to enable Transparent Huge Page alignment of the Erlang VM executable are only applied to the Erlang VM and not other native programs such as erlc and dialyzer. This bug was introduced in Erlang/OTP 27.0.

          Own Id: OTP-19137 Aux Id: GH-8574

        • When no time warp mode was enabled, a smaller Erlang monotonic time could be read than a previously read time, i.e., breaking the monotonic property. The runtime system will abort when detecting an issue like this since OTP 24.3.4.17 and OTP 25.0.

          Up until OTP 25 no time warp mode is the default. As of OTP 26 multi time warp mode is the default.

          Own Id: OTP-19147 Aux Id: ERIERL-1043, ERIERL-1106, PR-8619

        • When calling trace:function(Session, _, true, [meta]) the meta tracer was incorrectly set to be the calling process. Now it's set to the session tracer as expected.

          Own Id: OTP-19151 Aux Id: PR-8616, GH-8614

        Erts 15.0

        Fixed Bugs and Malfunctions

        • Bugs in how erl -extra interacts with passing flags via ERL_*FLAGS or -args_file have been fixed.

          Own Id: OTP-18766 Aux Id: PR-7639

        • Fixed a bug that prevented the emulator from building on recent versions of Yocto Linux.

          Own Id: OTP-18918 Aux Id: PR-7952

        • Fixed spectre mitigation configure test to work with GCC patches to always add -fcf-protection=full.

          Own Id: OTP-18928 Aux Id: PR-8006

        • A call to socket:[recv|recvfrom|recvmsg]/* with Timeout = 0 on Windows could cause a (case clause) crash if data is immediately available.

          Own Id: OTP-19063 Aux Id: OTP-18835

        • Fix bug on Windows where exit_status would not be sent when a port exits after the stdin/stdout handles have been closed.

          Own Id: OTP-19077 Aux Id: PR-8324

        Improvements and New Features

        • Refactored how the JIT handles POSIX signals and how they affect thread stacks, allowing us to use the native stack register for Erlang stacks on more platforms.

          Notably, containers built on 64-bit x86 Alpine Linux images will now perform much better in sequential code. As an example, running dialyzer over the OTP code base finishes about 15% quicker.

          Own Id: OTP-18568 Aux Id: PR-7174

        • The instrument module can now track allocations on a per-process or per-port basis.

          Own Id: OTP-18577 Aux Id: PR-7236

        • The pid field returned from erlang:fun_info/1,2 is now always the pid for the init process of the local node, not the pid for the actual process that created the fun.

          POTENTIAL INCOMPATIBILITY

          Own Id: OTP-18594 Aux Id: PR-7274

        • By default, escripts will now be compiled instead of interpreted. That means that the compiler application must be installed.

          POTENTIAL INCOMPATIBILITY

          Own Id: OTP-18639 Aux Id: PR-7348

        • A binary returned from the socket receive functions is no longer created as a sub binary of an often large receive buffer binary (socket option {otp,rcvbuf}). This avoids space waste, trusting the allocators to implement reallocation efficiently.

          Own Id: OTP-18642 Aux Id: GH-6152, PR-7465

        • The default process limit has been raised to 1048576 processes.

          Own Id: OTP-18699 Aux Id: PR-7388

        • The erlang:system_monitor/2 functionality is now able to monitor long message queues in the system.

          Own Id: OTP-18709 Aux Id: PR-7651

        • The erl command now supports the -S flag, which is similar to the -run flag, except that it will pass all arguments up to end of the command line to the called function. (The -run flag will not pass arguments beginning with a hyphen.) Another difference is that -S will always call a function with one argument, passing an empty list if no arguments were given.

          Own Id: OTP-18744 Aux Id: PR-7470

        • When implementing an alternative carrier for the Erlang distribution, a separate input handler process may now be registered, using erlang:dist_ctrl_input_handler/2, also in the case when the distribution controller is a port.

          Own Id: OTP-18774 Aux Id: PR-7110

        • The call stack trace has now been added to the error reported by erlang:process_flag/2 when max_heap_size limit has been exceeded.

          Own Id: OTP-18779 Aux Id: PR-7592

        • -callback attributes have been added to erl_tracer.

          Own Id: OTP-18794 Aux Id: PR-7703

        • For inet_backend = socket, setting the active socket option alone, to once, true or N has been optimized, as well as the corresponding data delivery.

          Own Id: OTP-18835

        • New functions socket:sendv/* for sending I/O vectors have been added.

          Own Id: OTP-18845

        • Socket options that take string now also accept binaries.

          Own Id: OTP-18849 Aux Id: PR-6510

        • Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code.

          There are also new APIs to support native coverage without using the cover tool.

          To instrument code for native coverage it must be compiled with the line_coverage option.

          To enable native coverage in the runtime system, start it like so:

          $ erl +JPcover true

          There are also the following new functions for supporting native coverage:

          Own Id: OTP-18856 Aux Id: PR-7856

        • Changed the default value of the command line flag -code_path_choice to strict.

          Note that for application systems using archives, it is necessary to add the code_path_choice relaxed to the command line that invokes erl.

          Own Id: OTP-18894 Aux Id: PR-7243

        • Added module loading to erl -init_debug printouts.

          Own Id: OTP-18929 Aux Id: PR-8004

        • When the runtime system halts, it performs various flush operations before terminating. By default there is no limit on how much time the flush operations are allowed to take. A new halt flush timeout functionality has been introduced which can be used for limiting the amount of time that the flushing operations are allowed to take. For more information see the documentation of the flush_timeout option of the erlang:halt/2 BIF and the documentation of the erl +zhft <Timeout> command line flag.

          Own Id: OTP-18938 Aux Id: PR-8035, GH-7438

        • Optimized code loading by moving certain operations from the code server to the caller.

          Own Id: OTP-18941 Aux Id: PR-7981

        • Updated asmjit to version a465fe71ab3d0e224b2b4bd0fac69ae68ab9239d

          Own Id: OTP-18942

        • The deprecated functions in zlib have been removed. That includes inflateChunk/{1,2}, getBufSize/1, setBufSize/2, the CRC32 functions, and the Adler checksum functions.

          Own Id: OTP-18950

        • The documentation has been migrated to use Markdown and ExDoc.

          Own Id: OTP-18955 Aux Id: PR-8026

        • Safe destructive update of tuples has been implemented in the compiler and runtime system. This allows the VM to update tuples in-place when it is safe to do so, thus improving performance by doing less copying but also by producing less garbage.

          Example:

          -record(rec, {a,b,c}).
           
          -update(#href_anchor"ss">rec{a=needs_update,b=N}=R0) ->
          -    R = R0#rec{a=up_to_date},
          +update(#href_anchor"ss">rec{a=needs_update,b=N}=R0) ->
          +    R = R0#rec{a=up_to_date},
               if
                   N < 0 ->
          -            R#rec{c=negative};
          +            R#rec{c=negative};
                   N == 0 ->
          -            R#rec{c=zero};
          +            R#rec{c=zero};
                   N > 0 ->
          -            R#rec{c=positive}
          +            R#rec{c=positive}
               end.

          The record updates in each of the three clauses of the if can safely be done in-place, because variable R is not used again.

          Own Id: OTP-18972 Aux Id: PR-8090

        • The obsolete and undocumented support for opening a port to an external resource by passing an atom (or a string) as first argument to open_port(), implemented by the vanilla driver, @@ -1514,9 +1514,9 @@ has now been removed.

          * POTENTIAL INCOMPATIBILITY *

          Own Id: OTP-16329 Aux Id: OTP-15621

        • The return value when using the httph and httph_bin option to erlang:decode_packet/3 and inet:setopts/2 has been changed to also include the original header unmodified. See erlang:decode_packet/3. Example:

           >
          -      erlang:decode_packet(httph_bin,<<"HELLO:
          -      hi\r\n\r\n">>,[]).
          -      {ok,{http_header,0,<<"Hello">>,<<"HELLO">>,<<"hi">>},<<"\r\n">>}

          Own Id: OTP-16347 Aux Id: PR-2466

        • Ensure net_kernel:monitor_nodes/1 sends nodedown messages of a failed + erlang:decode_packet(httph_bin,<<"HELLO: + hi\r\n\r\n">>,[]). + {ok,{http_header,0,<<"Hello">>,<<"HELLO">>,<<"hi">>},<<"\r\n">>}

          Own Id: OTP-16347 Aux Id: PR-2466

        • Ensure net_kernel:monitor_nodes/1 sends nodedown messages of a failed connection before nodeup messages of a reestablished connection toward the same node.

          Own Id: OTP-16362

        • Update of sequential tracing to also support other information transfers than message passing.

          Own Id: OTP-16370 Aux Id: OTP-15251, OTP-15232

        • socket: It is now possible to create a socket from an already existing file @@ -5885,12 +5885,12 @@ viewed as two operations performed atomically. Asynchronously send an unlink signal or a demonitor signal, and ignore any future results of the link or monitor.

          NOTE: This change can cause some obscure code to fail which previously did -not. For example, the following code might hang:

                      Mon = erlang:monitor(process, Pid),
          +not. For example, the following code might hang:

                      Mon = erlang:monitor(process, Pid),
                       %% ...
          -            exit(Pid, bang),
          -            erlang:demonitor(Mon),
          +            exit(Pid, bang),
          +            erlang:demonitor(Mon),
                       receive
          -                {'DOWN', Mon , process, Pid, _} -> ok
          +                {'DOWN', Mon , process, Pid, _} -> ok
                       %% We were previously guaranteed to get a down message
                       %% (since we exited the process ourself), so we could
                       %% in this case leave out:
          /usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/persistent_term.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
          --- old//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/persistent_term.html	2026-08-21 04:00:18.483288642 +0000
          +++ new//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/persistent_term.html	2026-08-21 04:00:18.483288642 +0000
          @@ -147,9 +147,9 @@
           collected into a larger term, for example, a map or a tuple.

          Example

          The following example shows how lock contention for ETS tables can be minimized by having one ETS table for each scheduler. The table identifiers for the ETS tables are stored as a single persistent term:

              %% There is one ETS table for each scheduler.
          -    Sid = erlang:system_info(scheduler_id),
          -    Tid = element(Sid, persistent_term:get(?MODULE)),
          -    ets:update_counter(Tid, Key, 1).
          +
          Sid = erlang:system_info(scheduler_id), + Tid = element(Sid, persistent_term:get(?MODULE)), + ets:update_counter(Tid, Key, 1).
    /usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/supercarrier.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/supercarrier.html 2026-08-21 04:00:18.499288746 +0000 +++ new//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/supercarrier.html 2026-08-21 04:00:18.499288746 +0000 @@ -163,12 +163,12 @@ and free entire pages and we don't want to waste an entire page just to hold the block header of the following pages.

    Instead we store the meta information about all the free segments in a dedicated area apart from the sa and sua areas. Every free segment is -represented by a descriptor struct (ErtsFreeSegDesc).

    typedef struct {
    +represented by a descriptor struct (ErtsFreeSegDesc).

    typedef struct {
         RBTNode snode;      /* node in 'stree' */
         RBTNode anode;      /* node in 'atree' */
         char* start;
         char* end;
    -}ErtsFreeSegDesc;

    To find the smallest free segment that will satisfy a carrier allocation +}ErtsFreeSegDesc;

    To find the smallest free segment that will satisfy a carrier allocation (best fit), the free segments are organized in a tree sorted by size (stree). We search in this tree at allocation. If no free segment of sufficient size was found, the area (sa or sua) is instead expanded. /usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/time_correction.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2677)) --- old//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/time_correction.html 2026-08-21 04:00:18.519288876 +0000 +++ new//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/time_correction.html 2026-08-21 04:00:18.519288876 +0000 @@ -366,9 +366,9 @@ the event occurs.

    Do

    Determine the order of events by saving a tuple containing monotonic time and a strictly monotonically increasing integer as -follows:

    Time = erlang:monotonic_time(),
    -UMI = erlang:unique_integer([monotonic]),
    -EventTag = {Time, UMI}

    These tuples are strictly monotonically ordered on the current runtime system +follows:

    Time = erlang:monotonic_time(),
    +UMI = erlang:unique_integer([monotonic]),
    +EventTag = {Time, UMI}

    These tuples are strictly monotonically ordered on the current runtime system instance according to creation time. It is important that the monotonic time is in the first element (the most significant element when comparing two-tuples). Using the monotonic time in the tuples, you can calculate time /usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/tracing.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/tracing.html 2026-08-21 04:00:18.538289000 +0000 +++ new//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/tracing.html 2026-08-21 04:00:18.538289000 +0000 @@ -101,23 +101,23 @@ to inspecting the stack we can only say where we're going to return to, which is not quite the same thing.

    As an illustration, when the caller option is enabled all trace messages from bar/1 will say that they were called from foo/0, even though it -went through a bunch of other functions on the way:

    foo() ->
    -    lots(),
    +went through a bunch of other functions on the way:

    foo() ->
    +    lots(),
         ok.
     
    -lots() ->
    -    'of'().
    +lots() ->
    +    'of'().
     
    -'of'() ->
    -    indirections().
    +'of'() ->
    +    indirections().
     
    -indirections() ->
    -    bar(10).
    +indirections() ->
    +    bar(10).
     
    -bar(0) ->
    +bar(0) ->
         done;
    -bar(N) ->
    -    bar(N - 1).

    Export tracing

    In the interpreter, breakpoints are set inside the code trampoline for +bar(N) -> + bar(N - 1).

    Export tracing

    In the interpreter, breakpoints are set inside the code trampoline for export entries, and their address vector is updated to point to them. This way, only remote calls will hit the breakpoint while local calls to the same function are left alone, but it otherwise acts the same way as /usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/zlib.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (810)) --- old//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/zlib.html 2026-08-21 04:00:18.565289176 +0000 +++ new//usr/share/doc/packages/erlang-doc/erts-16.4.0.4/doc/html/zlib.html 2026-08-21 04:00:18.565289176 +0000 @@ -98,18 +98,18 @@ data. The data format is described by RFC 1950, RFC 1951, and -RFC 1952.

    A typical (compress) usage is as follows:

    Z = zlib:open(),
    -ok = zlib:deflateInit(Z,default),
    +RFC 1952.

    A typical (compress) usage is as follows:

    Z = zlib:open(),
    +ok = zlib:deflateInit(Z,default),
     
    -Compress = fun F(end_of_data) ->
    -                 zlib:deflate(Z, [], finish);
    -               F(Data) ->
    -                 [zlib:deflate(Z, Data)|F(Read())]
    +Compress = fun F(end_of_data) ->
    +                 zlib:deflate(Z, [], finish);
    +               F(Data) ->
    +                 [zlib:deflate(Z, Data)|F(Read())]
                end,
    -Compressed = Compress(Read()),
    -ok = zlib:deflateEnd(Z),
    -zlib:close(Z),
    -list_to_binary(Compressed)

    In all functions errors, {'EXIT',{Reason,Backtrace}}, can be thrown, where +Compressed = Compress(Read()), +ok = zlib:deflateEnd(Z), +zlib:close(Z), +list_to_binary(Compressed)

    In all functions errors, {'EXIT',{Reason,Backtrace}}, can be thrown, where Reason describes the error.

    Typical Reasons:

    • badarg - Bad argument.

    • not_initialized - The stream hasn't been initialized, eg. if inflateInit/1 wasn't called prior to a call to inflate/2.

    • not_on_controlling_process - The stream was used by a process that doesn't control it. Use set_controlling_process/2 if you need to transfer a @@ -818,11 +818,11 @@ full too often can seriously degrade the compression.

      If Flush is set to finish, pending input is processed, pending output is flushed, and deflate/3 returns. Afterwards the only possible operations on the stream are deflateReset/1 or deflateEnd/1.

      Flush can be set to finish immediately after -deflateInit if all compression is to be done in one step.

      Example:

      zlib:deflateInit(Z),
      -B1 = zlib:deflate(Z,Data),
      -B2 = zlib:deflate(Z,<< >>,finish),
      -zlib:deflateEnd(Z),
      -list_to_binary([B1,B2])
      +deflateInit if all compression is to be done in one step.

      Example:

      zlib:deflateInit(Z),
      +B1 = zlib:deflate(Z,Data),
      +B2 = zlib:deflate(Z,<< >>,finish),
      +zlib:deflateEnd(Z),
      +list_to_binary([B1,B2])
    @@ -1374,20 +1374,20 @@ {'EXIT',{{need_dictionary,Adler},_StackTrace}} exception.

    The dictionary chosen by the compressor can be determined from the Adler value returned or thrown by the call to the inflate function. The compressor and decompressor must use the same dictionary (See deflateSetDictionary/2).

    After setting the dictionary the inflate operation should be retried without new -input.

    Example:

    deprecated_unpack(Z, Compressed, Dict) ->
    -     case catch zlib:inflate(Z, Compressed) of
    -          {'EXIT',{{need_dictionary,_DictID},_}} ->
    -                 ok = zlib:inflateSetDictionary(Z, Dict),
    -                 Uncompressed = zlib:inflate(Z, []);
    +input.

    Example:

    deprecated_unpack(Z, Compressed, Dict) ->
    +     case catch zlib:inflate(Z, Compressed) of
    +          {'EXIT',{{need_dictionary,_DictID},_}} ->
    +                 ok = zlib:inflateSetDictionary(Z, Dict),
    +                 Uncompressed = zlib:inflate(Z, []);
               Uncompressed ->
                      Uncompressed
          end.
     
    -new_unpack(Z, Compressed, Dict) ->
    -    case zlib:inflate(Z, Compressed, [{exception_on_need_dict, false}]) of
    -        {need_dictionary, _DictId, Output} ->
    -            ok = zlib:inflateSetDictionary(Z, Dict),
    -            [Output | zlib:inflate(Z, [])];
    +new_unpack(Z, Compressed, Dict) ->
    +    case zlib:inflate(Z, Compressed, [{exception_on_need_dict, false}]) of
    +        {need_dictionary, _DictId, Output} ->
    +            ok = zlib:inflateSetDictionary(Z, Dict),
    +            [Output | zlib:inflate(Z, [])];
             Uncompressed ->
                 Uncompressed
         end.
    @@ -1463,18 +1463,18 @@ desired, and the function will return {finished, Output} once all queued data has been decompressed.

    This function can introduce some output latency (reading input without producing any output).

    If a preset dictionary is required for further decompression, this function -returns a need_dictionary tuple. See inflateSetDictionary/2) for details.

    Example:

    walk(Compressed, Handler) ->
    -    Z = zlib:open(),
    -    zlib:inflateInit(Z),
    -    loop(Z, Handler, zlib:safeInflate(Z, Compressed)),
    -    zlib:inflateEnd(Z),
    -    zlib:close(Z).
    -
    -loop(Z, Handler, {continue, Output}) ->
    -    Handler(Output),
    -    loop(Z, Handler, zlib:safeInflate(Z, []));
    -loop(Z, Handler, {finished, Output}) ->
    -    Handler(Output).
    +returns a need_dictionary tuple. See inflateSetDictionary/2) for details.

    Example:

    walk(Compressed, Handler) ->
    +    Z = zlib:open(),
    +    zlib:inflateInit(Z),
    +    loop(Z, Handler, zlib:safeInflate(Z, Compressed)),
    +    zlib:inflateEnd(Z),
    +    zlib:close(Z).
    +
    +loop(Z, Handler, {continue, Output}) ->
    +    Handler(Output),
    +    loop(Z, Handler, zlib:safeInflate(Z, []));
    +loop(Z, Handler, {finished, Output}) ->
    +    Handler(Output).
    /usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/asn1ct.xhtml differs (HTML document, ASCII text, with very long lines (1289)) --- old//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/asn1ct.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/asn1ct.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -378,9 +378,9 @@ mostly work for old specifications based on the 1997 standard for ASN.1, but not for most modern-style applications. Another limitation is that the test functions may not work if options that change code generations strategies such -as the options macro_name_prefix and record_name_prefix have been used.

    • test/1 iterates over all types in Module.
    • test/2 tests type Type with a random value.
    • test/3 tests type Type with Value.

    Schematically, the following occurs for each type in the module:

    {ok, Value} = asn1ct:value(Module, Type),
    -{ok, Bytes} = Module:encode(Type, Value),
    -{ok, Value} = Module:decode(Type, Bytes).

    The test functions use the *.asn1db files for all included modules. If they +as the options macro_name_prefix and record_name_prefix have been used.

    • test/1 iterates over all types in Module.
    • test/2 tests type Type with a random value.
    • test/3 tests type Type with Value.

    Schematically, the following occurs for each type in the module:

    {ok, Value} = asn1ct:value(Module, Type),
    +{ok, Bytes} = Module:encode(Type, Value),
    +{ok, Value} = Module:decode(Type, Bytes).

    The test functions use the *.asn1db files for all included modules. If they are located in a different directory than the current working directory, use the include option to add paths. This is only needed when automatically generating values. For static values using Value no options are needed.

    /usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/asn1_getting_started.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (2610)) --- old//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/asn1_getting_started.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/asn1_getting_started.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -29,37 +29,37 @@ the syntax is correct and that the text represents proper ASN.1 code before generating an abstract syntax tree. The code generator then uses the abstract syntax tree to generate code.

    The generated Erlang files are placed in the current directory or in the -directory specified with option {outdir,Dir}.

    The compiler can be called from the Erlang shell like this:

    1> asn1ct:compile("People", [ber]).
    -ok

    Option verbose can be added to get information about the generated files:

    2> asn1ct:compile("People", [ber,verbose]).
    +directory specified with option {outdir,Dir}.

    The compiler can be called from the Erlang shell like this:

    1> asn1ct:compile("People", [ber]).
    +ok

    Option verbose can be added to get information about the generated files:

    2> asn1ct:compile("People", [ber,verbose]).
     Erlang ASN.1 compiling "People.asn"
    ---{generated,"People.asn1db"}--
    ---{generated,"People.hrl"}--
    ---{generated,"People.erl"}--
    +--{generated,"People.asn1db"}--
    +--{generated,"People.hrl"}--
    +--{generated,"People.erl"}--
     ok

    ASN.1 module People is now accepted and the abstract syntax tree is saved in file People.asn1db. The generated Erlang code is compiled using the Erlang compiler and loaded into the Erlang runtime system. There is now an API for -encode/2 and decode/2 in module People, which is called like this:

    'People':encode(<Type name>, <Value>)

    or:

    'People':decode(<Type name>, <Value>)

    Assume that there is a network application that receives instances of the ASN.1 +encode/2 and decode/2 in module People, which is called like this:

    'People':encode(<Type name>, <Value>)

    or:

    'People':decode(<Type name>, <Value>)

    Assume that there is a network application that receives instances of the ASN.1 defined type Person, modifies, and sends them back again:

    receive
    -   {Port,{data,Bytes}} ->
    -       case 'People':decode('Person',Bytes) of
    -           {ok,P} ->
    -               {ok,Answer} = 'People':encode('Person',mk_answer(P)),
    -               Port ! {self(),{command,Answer}};
    -           {error,Reason} ->
    -               exit({error,Reason})
    +   {Port,{data,Bytes}} ->
    +       case 'People':decode('Person',Bytes) of
    +           {ok,P} ->
    +               {ok,Answer} = 'People':encode('Person',mk_answer(P)),
    +               Port ! {self(),{command,Answer}};
    +           {error,Reason} ->
    +               exit({error,Reason})
            end
         end,

    In this example, a series of bytes is received from an external source and the bytes are then decoded into a valid Erlang term. This was achieved with the call 'People':decode('Person',Bytes), which returned an Erlang value of the ASN.1 type Person. Then an answer was constructed and encoded using 'People':encode('Person',Answer), which takes an instance of a defined ASN.1 -type and transforms it to a binary according to the BER or PER encoding rules.

    The encoder and decoder can also be run from the shell:

    2> Rockstar = {'Person',"Some Name",roving,50}.
    -{'Person',"Some Name",roving,50}
    -3> {ok,Bin} = 'People':encode('Person',Rockstar).
    -{ok,<<243,17,19,9,83,111,109,101,32,78,97,109,101,2,1,2,
    -      2,1,50>>}
    -4> {ok,Person} = 'People':decode('Person',Bin).
    -{ok,{'Person',"Some Name",roving,50}}

    Module Dependencies

    It is common that ASN.1 modules import defined types, values, and other entities +type and transforms it to a binary according to the BER or PER encoding rules.

    The encoder and decoder can also be run from the shell:

    2> Rockstar = {'Person',"Some Name",roving,50}.
    +{'Person',"Some Name",roving,50}
    +3> {ok,Bin} = 'People':encode('Person',Rockstar).
    +{ok,<<243,17,19,9,83,111,109,101,32,78,97,109,101,2,1,2,
    +      2,1,50>>}
    +4> {ok,Person} = 'People':decode('Person',Bin).
    +{ok,{'Person',"Some Name",roving,50}}

    Module Dependencies

    It is common that ASN.1 modules import defined types, values, and other entities from another ASN.1 module.

    Earlier versions of the ASN.1 compiler required that modules that were imported from had to be compiled before the module that imported. This caused problems when ASN.1 modules had circular dependencies.

    Referenced modules are now parsed when the compiler finds an entity that is @@ -100,16 +100,16 @@ module and the NIF library in asn1/priv_dir are needed at runtime.

    By calling function info/0 in a generated module, you get information about which compiler options were used.

    Special Decode Functionality for JSON Encoding Rules (JER)

    When using the JSON encoding rules, it is possible to call the decode/2 function in the following way with data that has already -been decoded by json:decode/1:

    SomeModule:decode(Type, {json_decoded, Decoded}).

    Example:

    1> asn1ct:compile("People", [jer]).
    +been decoded by json:decode/1:

    SomeModule:decode(Type, {json_decoded, Decoded}).

    Example:

    1> asn1ct:compile("People", [jer]).
     ok
    -2> Rockstar = {'Person',"Vince Eclipse",roving,50}.
    -{'Person',"Vince Eclipse",roving,50}
    -3> {ok,Bin} = 'People':encode('Person', Rockstar).
    -{ok,<<"{\"name\":\"Vince Eclipse\",\"location\":2,\"age\":50}">>}
    -4> 'People':decode('Person', Bin).
    -{ok,{'Person',"Vince Eclipse",roving,50}}
    -5> 'People':decode('Person', {json_decoded,json:decode(Bin)}).
    -{ok,{'Person',"Vince Eclipse",roving,50}}
    +2> Rockstar = {'Person',"Vince Eclipse",roving,50}.
    +{'Person',"Vince Eclipse",roving,50}
    +3> {ok,Bin} = 'People':encode('Person', Rockstar).
    +{ok,<<"{\"name\":\"Vince Eclipse\",\"location\":2,\"age\":50}">>}
    +4> 'People':decode('Person', Bin).
    +{ok,{'Person',"Vince Eclipse",roving,50}}
    +5> 'People':decode('Person', {json_decoded,json:decode(Bin)}).
    +{ok,{'Person',"Vince Eclipse",roving,50}}
     

    Errors

    Errors detected at compile-time are displayed on the screen together with line numbers indicating where in the source file the respective error was detected. If no errors are found, an Erlang ASN.1 module is created.

    The runtime encoders and decoders execute within a catch and return {ok, Data} @@ -127,30 +127,30 @@ to manually add tags to certain constructs in order for the ASN.1 specification to be valid. Example of an old-style specification:

    Tags DEFINITIONS ::=
     BEGIN
    -  Afters ::= CHOICE { cheese [0] IA5String,
    -                      dessert [1] IA5String }
    +  Afters ::= CHOICE { cheese [0] IA5String,
    +                      dessert [1] IA5String }
     END

    Without the tags (the numbers in square brackets) the ASN.1 compiler refused to compile the file.

    In 1994 the global tagging mode AUTOMATIC TAGS was introduced. By putting AUTOMATIC TAGS in the module header, the ASN.1 compiler automatically adds tags when needed. The following is the same specification in AUTOMATIC TAGS mode:

    Tags DEFINITIONS AUTOMATIC TAGS ::=
     BEGIN
    -  Afters ::= CHOICE { cheese IA5String,
    -                      dessert IA5String }
    +  Afters ::= CHOICE { cheese IA5String,
    +                      dessert IA5String }
     END

    ASN.1 Types

    This section describes the ASN.1 types including their functionality, purpose, and how values are assigned in Erlang.

    ASN.1 has both primitive and constructed types:

    Primitive TypesConstructed Types
    BOOLEANSEQUENCE
    INTEGERSET
    REALCHOICE
    NULLSET OF and SEQUENCE OF
    ENUMERATEDANY
    BIT STRINGANY DEFINED BY
    OCTET STRINGEXTERNAL
    Character StringsEMBEDDED PDV
    OBJECT IDENTIFIERCHARACTER STRING
    Object Descriptor
    TIME Types

    Table: Supported ASN.1 Types

    Note

    The values of each ASN.1 type have their own representation in Erlang, as described in the following sections. Users must provide these values for encoding according to the representation, as shown in the following example:

    Operational ::= BOOLEAN --ASN.1 definition

    In Erlang code it can look as follows:

    Val = true,
    -{ok,Bytes} = MyModule:encode('Operational', Val),

    BOOLEAN

    Booleans in ASN.1 express values that can be either TRUE or FALSE. The +{ok,Bytes} = MyModule:encode('Operational', Val),

    BOOLEAN

    Booleans in ASN.1 express values that can be either TRUE or FALSE. The meanings assigned to TRUE and FALSE are outside the scope of this text.

    In ASN.1 it is possible to have:

    Operational ::= BOOLEAN

    Assigning a value to type Operational in Erlang is possible by using the following Erlang code:

    Myvar1 = true,

    Thus, in Erlang the atoms true and false are used to encode a boolean value.

    INTEGER

    An ASN.1 INTEGER is represented by an integer in Erlang.

    The concept of subtyping can be applied to integers and to other ASN.1 types. The details of subtyping are not explained here; for more information, see X.680. Various syntaxes are allowed when defining a type as an integer:

    T1 ::= INTEGER
    -T2 ::= INTEGER (-2..7)
    -T3 ::= INTEGER (0..MAX)
    -T4 ::= INTEGER (0<..MAX)
    -T5 ::= INTEGER (MIN<..-99)
    -T6 ::= INTEGER {red(0),blue(1),white(2)}

    The Erlang representation of an ASN.1 INTEGER is an integer or an atom if a +T2 ::= INTEGER (-2..7) +T3 ::= INTEGER (0..MAX) +T4 ::= INTEGER (0<..MAX) +T5 ::= INTEGER (MIN<..-99) +T6 ::= INTEGER {red(0),blue(1),white(2)}

    The Erlang representation of an ASN.1 INTEGER is an integer or an atom if a Named Number List (see T6 in the previous list) is specified.

    The following is an example of Erlang code that assigns values for the types in the previous list:

    T1value = 0,
     T2value = 6,
    @@ -175,7 +175,7 @@
     specified values, whereas an integer can have any value.

    BIT STRING

    The type BIT STRING can be used to model information that is made up of arbitrary length series of bits. It is intended to be used for selection of flags, not for binary files.

    In ASN.1, BIT STRING definitions can look as follows:

    Bits1 ::= BIT STRING
    -Bits2 ::= BIT STRING {foo(0),bar(1),gnu(2),gnome(3),punk(14)}

    The following two notations are available for representation of BIT STRING +Bits2 ::= BIT STRING {foo(0),bar(1),gnu(2),gnome(3),punk(14)}

    The following two notations are available for representation of BIT STRING values in Erlang and as input to the encode functions:

    1. A bitstring. By default, a BIT STRING with no symbolic names is decoded to an Erlang bitstring.
    2. A list of atoms corresponding to atoms in the NamedBitList in the BIT STRING definition. A BIT STRING with symbolic names is always decoded @@ -197,7 +197,7 @@ misinterpret a BIT STRING value in this format.

    OCTET STRING

    OCTET STRING is the simplest of all ASN.1 types. OCTET STRING only moves or transfers, for example, binary files or other unstructured information complying with two rules: the bytes consist of octets and encoding is not required.

    It is possible to have the following ASN.1 type definitions:

    O1 ::= OCTET STRING
    -O2 ::= OCTET STRING (SIZE(28))

    With the following example assignments in Erlang:

    O1Val = <<17,13,19,20,0,0,255,254>>,
    +O2 ::= OCTET STRING (SIZE(28))

    With the following example assignments in Erlang:

    O1Val = <<17,13,19,20,0,0,255,254>>,
     O2Val = <<"must be exactly 28 chars....">>,

    By default, an OCTET STRING is always represented as an Erlang binary. If the specification has been compiled with option legacy_erlang_types, the encode functions accept both lists and binaries, and the decode functions decode an @@ -212,11 +212,11 @@ of view, octets are very similar to character strings and are compiled in the same way.

    When PER is used, there is a significant difference in the encoding scheme for OCTET STRINGs and other strings. The constraints specified for a type -are especially important for PER, because they affect the encoding.

    Examples:

    Digs ::= NumericString (SIZE(1..3))
    -TextFile ::= IA5String (SIZE(0..64000))

    The corresponding Erlang assignments:

    DigsVal1 = "456",
    +are especially important for PER, because they affect the encoding.

    Examples:

    Digs ::= NumericString (SIZE(1..3))
    +TextFile ::= IA5String (SIZE(0..64000))

    The corresponding Erlang assignments:

    DigsVal1 = "456",
     DigsVal2 = "123",
     TextFileVal1 = "abc...xyz...",
    -TextFileVal2 = [88,76,55,44,99,121 .......... a lot of characters here ....]

    The Erlang representation for BMPString and UniversalString is either a list +TextFileVal2 = [88,76,55,44,99,121 .......... a lot of characters here ....]

    The Erlang representation for BMPString and UniversalString is either a list of ASCII values or a list of quadruples. The quadruple representation associates to the Unicode standard representation of characters. The ASCII characters are all represented by quadruples beginning with three zeros like {0,0,0,65} for @@ -225,49 +225,49 @@ in file PrimStrings.asn1:

    PrimStrings DEFINITIONS AUTOMATIC TAGS ::=
     BEGIN
        BMP ::= BMPString
    -END

    Encoding and decoding some strings:

    1> asn1ct:compile('PrimStrings', [ber]).
    +END

    Encoding and decoding some strings:

    1> asn1ct:compile('PrimStrings', [ber]).
     ok
    -2> {ok,Bytes1} = 'PrimStrings':encode('BMP', [{0,0,53,53},{0,0,45,56}]).
    -{ok,<<30,4,53,54,45,56>>}
    -3> 'PrimStrings':decode('BMP', Bytes1).
    -{ok,[{0,0,53,53},{0,0,45,56}]}
    -4> {ok,Bytes2} = 'PrimStrings':encode('BMP', [{0,0,53,53},{0,0,0,65}]).
    -{ok,<<30,4,53,53,0,65>>}
    -5> 'PrimStrings':decode('BMP', Bytes2).
    -{ok,[{0,0,53,53},65]}
    -6> {ok,Bytes3} = 'PrimStrings':encode('BMP', "BMP string").
    -{ok,<<30,20,0,66,0,77,0,80,0,32,0,115,0,116,0,114,0,105,0,110,0,103>>}
    -7> 'PrimStrings':decode('BMP', Bytes3).
    -{ok,"BMP string"}

    Type UTF8String is represented as a UTF-8 encoded binary in Erlang. Such +2> {ok,Bytes1} = 'PrimStrings':encode('BMP', [{0,0,53,53},{0,0,45,56}]). +{ok,<<30,4,53,54,45,56>>} +3> 'PrimStrings':decode('BMP', Bytes1). +{ok,[{0,0,53,53},{0,0,45,56}]} +4> {ok,Bytes2} = 'PrimStrings':encode('BMP', [{0,0,53,53},{0,0,0,65}]). +{ok,<<30,4,53,53,0,65>>} +5> 'PrimStrings':decode('BMP', Bytes2). +{ok,[{0,0,53,53},65]} +6> {ok,Bytes3} = 'PrimStrings':encode('BMP', "BMP string"). +{ok,<<30,20,0,66,0,77,0,80,0,32,0,115,0,116,0,114,0,105,0,110,0,103>>} +7> 'PrimStrings':decode('BMP', Bytes3). +{ok,"BMP string"}

    Type UTF8String is represented as a UTF-8 encoded binary in Erlang. Such binaries can be created directly using the binary syntax or by converting from a list of Unicode code points using function unicode:characters_to_binary/1.

    The following shows examples of how UTF-8 encoded binaries can be created and manipulated:

    1> Gs = "Мой маленький Гном".
    -[1052,1086,1081,32,1084,1072,1083,1077,1085,1100,1082,1080,
    - 1081,32,1043,1085,1086,1084]
    -2> Gbin = unicode:characters_to_binary(Gs).
    -<<208,156,208,190,208,185,32,208,188,208,176,208,187,208,
    +[1052,1086,1081,32,1084,1072,1083,1077,1085,1100,1082,1080,
    + 1081,32,1043,1085,1086,1084]
    /usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/asn1_spec.xhtml differs (HTML document, ASCII text, with very long lines (1512))
    --- old//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/asn1_spec.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/asn1_spec.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -39,31 +39,31 @@
     exclusive decode is enabled. This function decodes the parts that
     were left undecoded during the exclusive decode.

    Both functions are described in the following.

    If the exclusive decode function has, for example, the name decode_exclusive and an ASN.1 encoded message Bin is to be exclusive decoded, the call is as -follows:

    {ok,ExclMessage} = 'MyModule':decode_exclusive(Bin)

    The result ExclMessage has the same structure as a +follows:

    {ok,ExclMessage} = 'MyModule':decode_exclusive(Bin)

    The result ExclMessage has the same structure as a complete decode would have, except for the parts of the top type that were not decoded. The undecoded parts are on their places in the structure on format {TypeKey,UndecodedValue}.

    Each undecoded part that is to be decoded must be fed into function -decode_part/2 as follows:

    {ok,PartMessage} = 'MyModule':decode_part(TypeKey, UndecodedValue)

    Writing an Exclusive Decode Instruction

    This instruction is written in the configuration file in the following format:

    ExclusiveDecodeInstruction = {exclusive_decode,{ModuleName,DecodeInstructions}}.
    +decode_part/2 as follows:

    {ok,PartMessage} = 'MyModule':decode_part(TypeKey, UndecodedValue)

    Writing an Exclusive Decode Instruction

    This instruction is written in the configuration file in the following format:

    ExclusiveDecodeInstruction = {exclusive_decode,{ModuleName,DecodeInstructions}}.
     
    -ModuleName = atom()
    +ModuleName = atom()
     
    -DecodeInstructions = [DecodeInstruction]+
    +DecodeInstructions = [DecodeInstruction]+
     
    -DecodeInstruction = {ExclusiveDecodeFunctionName,TypeList}
    +DecodeInstruction = {ExclusiveDecodeFunctionName,TypeList}
     
    -ExclusiveDecodeFunctionName = atom()
    +ExclusiveDecodeFunctionName = atom()
     
    -TypeList = [TopType,ElementList]
    +TypeList = [TopType,ElementList]
     
    -ElementList = [Element]+
    +ElementList = [Element]+
     
    -Element = {Name,parts} |
    -          {Name,undecoded} |
    -          {Name,ElementList}
    +Element = {Name,parts} |
    +          {Name,undecoded} |
    +          {Name,ElementList}
     
    -TopType = atom()
    +TopType = atom()
     
    -Name = atom()

    The instruction must be a valid Erlang term terminated by a dot.

    In TypeList the path from the top type to each undecoded subcomponent is +Name = atom()

    The instruction must be a valid Erlang term terminated by a dot.

    In TypeList the path from the top type to each undecoded subcomponent is described. TopType is the name of a top-level type in the ASN.1 specification. The action for each component in ElementList is described by one of:

    • {Name,parts}
    • {Name,undecoded}
    • {Name,ElementList}

    The use and effect of the actions are as follows:

    • {Name,undecoded} - Leaves the element undecoded. The type of Name can be any ASN.1 type. The value of element Name is returned as a tuple (as @@ -123,78 +123,78 @@ ['Button',[{number,undecoded}]]}]}}.

    The following figure shows the bytes of a Window:status message. The components buttonList and actions are excluded from decode. Only state and enabled are decoded when decode__Window_exclusive is called.

    Bytes of a Window:status Message

    Here follows an example of how the module. Note that option no_ok_wrapper is -used to make the example more concise.

    1> asn1ct:compile('GUI', [ber,asn1config,no_ok_wrapper]).
    +used to make the example more concise.

    1> asn1ct:compile('GUI', [ber,asn1config,no_ok_wrapper]).
     ok
    -2> rr('GUI').
    -['Action','Button','Status']
    -3> ButtonMsg = #'Button'{number=123,on=true}.
    -#'Button'{number = 123,on = true}
    -4> ButtonBytes = 'GUI':encode('Button', ButtonMsg).
    -<<48,6,128,1,123,129,1,255>>
    -5> ExclusiveMsgButton = 'GUI':decode_Button_exclusive(ButtonBytes).
    -#'Button'{number = {'Button_number',<<128,1,123>>},
    -          on = true}
    -6> {UndecKey,UndecBytes} = ExclusiveMsgButton#'Button'.number.
    -{'Button_number',<<128,1,123>>}
    -7> 'GUI':decode_part(UndecKey, UndecBytes).
    +2> rr('GUI').
    +['Action','Button','Status']
    +3> ButtonMsg = #'Button'{number=123,on=true}.
    +#'Button'{number = 123,on = true}
    +4> ButtonBytes = 'GUI':encode('Button', ButtonMsg).
    +<<48,6,128,1,123,129,1,255>>
    +5> ExclusiveMsgButton = 'GUI':decode_Button_exclusive(ButtonBytes).
    +#'Button'{number = {'Button_number',<<128,1,123>>},
    +          on = true}
    +6> {UndecKey,UndecBytes} = ExclusiveMsgButton#'Button'.number.
    +{'Button_number',<<128,1,123>>}
    +7> 'GUI':decode_part(UndecKey, UndecBytes).
     123
     8> WindowMsg =
    -{status,{'Status',35,
    -   [{'Button',3,true},
    -    {'Button',4,false},
    -    {'Button',5,true},
    -    {'Button',6,true},
    -    {'Button',7,false}],
    +{status,{'Status',35,
    +   [{'Button',3,true},
    +    {'Button',4,false},
    +    {'Button',5,true},
    +    {'Button',6,true},
    +    {'Button',7,false}],
        false,
    -   {possibleActions,[{'Action',16,{'Button',17,true}}]}}}.
    -{status,#'Status'{state = 35,
    -        buttonList = [#'Button'{number = 3,on = true},
    -                      #'Button'{number = 4,on = false},
    -                      #'Button'{number = 5,on = true},
    -                      #'Button'{number = 6,on = true},
    -                      #'Button'{number = 7,on = false}],
    +   {possibleActions,[{'Action',16,{'Button',17,true}}]}}}.
    +{status,#'Status'{state = 35,
    +        buttonList = [#'Button'{number = 3,on = true},
    +                      #'Button'{number = 4,on = false},
    +                      #'Button'{number = 5,on = true},
    +                      #'Button'{number = 6,on = true},
    +                      #'Button'{number = 7,on = false}],
             enabled = false,
    -        actions = {possibleActions,[#'Action'{number = 16,
    -                                              handle = #'Button'{number = 17,on = true}}]}}}
    -9> WindowBytes = 'GUI':encode('Window', WindowMsg).
    -<<161,65,128,1,35,161,40,48,6,128,1,3,129,1,255,48,6,128,
    -  1,4,129,1,0,48,6,128,1,5,129,...>>
    -10> {status,#'Status'{buttonList={UndecWindowKey,UndecWindowParts}}} =
    -'GUI':decode_Window_exclusive(WindowBytes).
    -{status,#'Status'{state = 35,
    -                  buttonList = {'Status_buttonList',[<<48,6,128,1,3,129,1,
    -                                                       255>>,
    -                                                     <<48,6,128,1,4,129,1,0>>,
    -                                                     <<48,6,128,1,5,129,1,255>>,
    -                                                     <<48,6,128,1,6,129,1,255>>,
    -                                                     <<48,6,128,1,7,129,1,0>>]},
    +        actions = {possibleActions,[#'Action'{number = 16,
    +                                              handle = #'Button'{number = 17,on = true}}]}}}
    +9> WindowBytes = 'GUI':encode('Window', WindowMsg).
    +<<161,65,128,1,35,161,40,48,6,128,1,3,129,1,255,48,6,128,
    +  1,4,129,1,0,48,6,128,1,5,129,...>>
    +10> {status,#'Status'{buttonList={UndecWindowKey,UndecWindowParts}}} =
    +'GUI':decode_Window_exclusive(WindowBytes).
    +{status,#'Status'{state = 35,
    +                  buttonList = {'Status_buttonList',[<<48,6,128,1,3,129,1,
    +                                                       255>>,
    +                                                     <<48,6,128,1,4,129,1,0>>,
    +                                                     <<48,6,128,1,5,129,1,255>>,
    +                                                     <<48,6,128,1,6,129,1,255>>,
    +                                                     <<48,6,128,1,7,129,1,0>>]},
                       enabled = false,
    -                  actions = {'Status_actions',<<163,15,160,13,48,11,128,
    +                  actions = {'Status_actions',<<163,15,160,13,48,11,128,
                                                     1,16,161,6,128,1,17,129,
    -                                                1,255>>}}}
    -11> 'GUI':decode_part(UndecWindowKey, UndecWindowParts).
    -[#'Button'{number = 3,on = true},
    - #'Button'{number = 4,on = false},
    - #'Button'{number = 5,on = true},
    - #'Button'{number = 6,on = true},
    - #'Button'{number = 7,on = false}]
    -12> 'GUI':decode_part(UndecWindowKey, hd(UndecWindowParts)).
    -#'Button'{number = 3,on = true}
    -13> {status,#'Status'{actions={ChoiceKey,ChoiceUndec}}} = v(10).
    -{status,#'Status'{state = 35,
    -                  buttonList = {'Status_buttonList',[<<48,6,128,1,3,129,1,
    -                                                       255>>,
    -                                                     <<48,6,128,1,4,129,1,0>>,
    -                                                     <<48,6,128,1,5,129,1,255>>,
    -                                                     <<48,6,128,1,6,129,1,255>>,
    -                                                     <<48,6,128,1,7,129,1,0>>]},
    +                                                1,255>>}}}
    +11> 'GUI':decode_part(UndecWindowKey, UndecWindowParts).
    +[#'Button'{number = 3,on = true},
    + #'Button'{number = 4,on = false},
    + #'Button'{number = 5,on = true},
    + #'Button'{number = 6,on = true},
    + #'Button'{number = 7,on = false}]
    +12> 'GUI':decode_part(UndecWindowKey, hd(UndecWindowParts)).
    +#'Button'{number = 3,on = true}
    +13> {status,#'Status'{actions={ChoiceKey,ChoiceUndec}}} = v(10).
    +{status,#'Status'{state = 35,
    +                  buttonList = {'Status_buttonList',[<<48,6,128,1,3,129,1,
    +                                                       255>>,
    +                                                     <<48,6,128,1,4,129,1,0>>,
    +                                                     <<48,6,128,1,5,129,1,255>>,
    +                                                     <<48,6,128,1,6,129,1,255>>,
    +                                                     <<48,6,128,1,7,129,1,0>>]},
                       enabled = false,
    -                  actions = {'Status_actions',<<163,15,160,13,48,11,128,
    +                  actions = {'Status_actions',<<163,15,160,13,48,11,128,
                                                     1,16,161,6,128,1,17,129,
    -                                                1,255>>}}}
    -14> 'GUI':decode_part(ChoiceKey, ChoiceUndec).
    -{possibleActions,[#'Action'{number = 16,
    -                            handle = #'Button'{number = 17,on = true}}]}

    Selective Decode

    Selective decode decodes a single subtype of a constructed value. This is the + 1,255>>}}} +14> 'GUI':decode_part(ChoiceKey, ChoiceUndec). +{possibleActions,[#'Action'{number = 16, + handle = #'Button'{number = 17,on = true}}]}

    Selective Decode

    Selective decode decodes a single subtype of a constructed value. This is the fastest method to extract a subvalue. Selective decode is typically used when one want to inspect, for example, a version number to be able to decide how to handle the entire value.

    Procedure

    To perform a selective decode:

    • Step 1: Include the following instructions in the configuration file:

      • The name of the user function
      • The name of the ASN.1 specification
      • A notation that tells which part of the type to be decoded
    • Step 2: Compile with the additional option asn1config. The compiler @@ -207,23 +207,23 @@ {selective_decode,{'ModuleName',[{selected_decode_Window,TypeList}]}} do the selective decode by {ok,Result} = 'ModuleName':selected_decode_Window(EncodedBinary).

      Writing a Selective Decode Instruction

      One or more selective decode functions can be described in a configuration file. -Use the following notation:

      SelectiveDecodeInstruction = {selective_decode,{ModuleName,DecodeInstructions}}.
      +Use the following notation:

      SelectiveDecodeInstruction = {selective_decode,{ModuleName,DecodeInstructions}}.
       
      -ModuleName = atom()
      +ModuleName = atom()
       
      -DecodeInstructions = [DecodeInstruction]+
      /usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text)
      --- old//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
      @@ -4,10 +4,10 @@
                version="3.0">
         
           asn1 - 5.4.3
      -    urn:uuid:ad2b7bdc-1ef5-7d21-c214-f1a48a7bdbba
      +    urn:uuid:09a53a67-937a-4ed3-0902-64776d283560
           en
       
      -    2026-08-21T03:48:15Z
      +    2042-09-22T17:07:01Z
       
         
         
      /usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/notes.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (10846))
      --- old//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/notes.xhtml	2026-08-05 05:56:49.000000000 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1.epub/OEBPS/notes.xhtml	2026-08-05 05:56:49.000000000 +0000
      @@ -17,7 +17,7 @@
         
       
           

      asn1 Release Notes

      -

      This document describes the changes made to the asn1 application.

      Asn1 5.4.3

      Improvements and New Features

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      Asn1 5.4.2

      Fixed Bugs and Malfunctions

      • Decoding a constrained BIT STRING using JER was broken.

        Own Id: OTP-19681 Aux Id: PR-9949

      • NIFs and linked-in drivers are now loadable when running in an Erlang source tree on Windows.

        Own Id: OTP-19686 Aux Id: PR-9969

      Asn1 5.4.1

      Fixed Bugs and Malfunctions

      • The ASN.1 compiler could generate code that would cause Dialyzer with the unmatched_returns option to emit warnings.

        Own Id: OTP-19638 Aux Id: GH-9841, PR-9846

      Asn1 5.4

      Fixed Bugs and Malfunctions

      • The undec_rest option would be ignored in generated functions for exclusive decode. The option is now respected, meaning that the return value from such functions are now three-tuples instead of a two-tuples.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19290 Aux Id: PR-8798

      Improvements and New Features

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      • The ancient ASN.1 modules used in public_key has been replaced with more modern versions, but we have strived to keep the documented Erlang API for the public_key application compatible.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19612 Aux Id: PR-9774

      Asn1 5.3.4.2

      Fixed Bugs and Malfunctions

      • Decoding a constrained BIT STRING using JER was broken.

        Own Id: OTP-19681 Aux Id: PR-9949

      Asn1 5.3.4.1

      Fixed Bugs and Malfunctions

      • The ASN.1 compiler could generate code that would cause Dialyzer with the unmatched_returns option to emit warnings.

        Own Id: OTP-19638 Aux Id: GH-9841, PR-9846

      Asn1 5.3.4

      Fixed Bugs and Malfunctions

      • Negative REAL numbers greater than -1 would be incorrectly encoded (the minus sign would be lost).

        Own Id: OTP-19567 Aux Id: ERIERL-1214, PR-9658

      Asn1 5.3.3

      Fixed Bugs and Malfunctions

      • The JER backend will now include the SIZE constraint in the type info for OCTET STRINGs, and a SIZE constraint with a range will now be included for BIT STRINGs. This does not change the actual encoding or decoding of JER, but can be useful for tools.

        Own Id: OTP-19542 Aux Id: ERIERL-1204, PR-9588

      Improvements and New Features

      • When using the JSON encoding rules, it is now possible to call the decode/2 function in the following way with data that has already been decoded by json:decode/1:

        SomeModule:decode(Type, {json_decoded, Decoded}).

        Own Id: OTP-19547 Aux Id: ERIERL-1206, PR-9611

      Asn1 5.3.2

      Fixed Bugs and Malfunctions

      • Multiple bugs in decoding of the REAL type has been eliminated. Also, the documentation for REAL has been updated to mention the special values 0, PLUS-INFINITY, and MINUS-INFINITY.

        Own Id: OTP-19504 Aux Id: GH-9096, PR-9469

      Asn1 5.3.1

      Fixed Bugs and Malfunctions

      • Fixed a cosmetic but harmless issue with the ASN.1 compiler passing on the undec_rest option to the Erlang compiler.

        Own Id: OTP-19218 Aux Id: GH-8779, PR-8781

      Asn1 5.3

      Fixed Bugs and Malfunctions

      Improvements and New Features

      • Specs have been added to all asn1ct API functions.

        Own Id: OTP-18804 Aux Id: PR-7738

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      • The jer (JSON Encoding Rules) for ASN.1 now use the new json module for encoding and decoding JSON. Thus, there is no longer any need for an external JSON library.

        Own Id: OTP-19018 Aux Id: PR-8241

      Asn1 5.2.2.1

      Fixed Bugs and Malfunctions

      • The ASN.1 compiler could generate code that would cause Dialyzer with the unmatched_returns option to emit warnings.

        Own Id: OTP-19638 Aux Id: GH-9841, PR-9846

      Asn1 5.2.2

      Fixed Bugs and Malfunctions

      • An ASN.1 module that contains named BIT STRING values would fail to compiled if both the BER and JER back-ends were enabled.

        Own Id: OTP-19039 Aux Id: GH-8291, PR-8297

      Asn1 5.2.1

      Fixed Bugs and Malfunctions

      • Fix benign warning from gcc 11 about mismatching call to free().

        Own Id: OTP-18844

      Asn1 5.2

      Fixed Bugs and Malfunctions

      • The ASN.1 compiler would ignore a constraint such as (SIZE (1..4), ...), +

        This document describes the changes made to the asn1 application.

        Asn1 5.4.3

        Improvements and New Features

        • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

          A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

          make release_docs places the documentation in the released code under the doc folder.

          make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

          The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

          Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

          Improves the source Software-Bill-of-Materials

          • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
          • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
          • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

          Own Id: OTP-19886 Aux Id: PR-10434

        Asn1 5.4.2

        Fixed Bugs and Malfunctions

        • Decoding a constrained BIT STRING using JER was broken.

          Own Id: OTP-19681 Aux Id: PR-9949

        • NIFs and linked-in drivers are now loadable when running in an Erlang source tree on Windows.

          Own Id: OTP-19686 Aux Id: PR-9969

        Asn1 5.4.1

        Fixed Bugs and Malfunctions

        • The ASN.1 compiler could generate code that would cause Dialyzer with the unmatched_returns option to emit warnings.

          Own Id: OTP-19638 Aux Id: GH-9841, PR-9846

        Asn1 5.4

        Fixed Bugs and Malfunctions

        • The undec_rest option would be ignored in generated functions for exclusive decode. The option is now respected, meaning that the return value from such functions are now three-tuples instead of a two-tuples.

          POTENTIAL INCOMPATIBILITY

          Own Id: OTP-19290 Aux Id: PR-8798

        Improvements and New Features

        • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

          Own Id: OTP-19575 Aux Id: PR-9670

        • The ancient ASN.1 modules used in public_key has been replaced with more modern versions, but we have strived to keep the documented Erlang API for the public_key application compatible.

          POTENTIAL INCOMPATIBILITY

          Own Id: OTP-19612 Aux Id: PR-9774

        Asn1 5.3.4.2

        Fixed Bugs and Malfunctions

        • Decoding a constrained BIT STRING using JER was broken.

          Own Id: OTP-19681 Aux Id: PR-9949

        Asn1 5.3.4.1

        Fixed Bugs and Malfunctions

        • The ASN.1 compiler could generate code that would cause Dialyzer with the unmatched_returns option to emit warnings.

          Own Id: OTP-19638 Aux Id: GH-9841, PR-9846

        Asn1 5.3.4

        Fixed Bugs and Malfunctions

        • Negative REAL numbers greater than -1 would be incorrectly encoded (the minus sign would be lost).

          Own Id: OTP-19567 Aux Id: ERIERL-1214, PR-9658

        Asn1 5.3.3

        Fixed Bugs and Malfunctions

        • The JER backend will now include the SIZE constraint in the type info for OCTET STRINGs, and a SIZE constraint with a range will now be included for BIT STRINGs. This does not change the actual encoding or decoding of JER, but can be useful for tools.

          Own Id: OTP-19542 Aux Id: ERIERL-1204, PR-9588

        Improvements and New Features

        • When using the JSON encoding rules, it is now possible to call the decode/2 function in the following way with data that has already been decoded by json:decode/1:

          SomeModule:decode(Type, {json_decoded, Decoded}).

          Own Id: OTP-19547 Aux Id: ERIERL-1206, PR-9611

        Asn1 5.3.2

        Fixed Bugs and Malfunctions

        • Multiple bugs in decoding of the REAL type has been eliminated. Also, the documentation for REAL has been updated to mention the special values 0, PLUS-INFINITY, and MINUS-INFINITY.

          Own Id: OTP-19504 Aux Id: GH-9096, PR-9469

        Asn1 5.3.1

        Fixed Bugs and Malfunctions

        • Fixed a cosmetic but harmless issue with the ASN.1 compiler passing on the undec_rest option to the Erlang compiler.

          Own Id: OTP-19218 Aux Id: GH-8779, PR-8781

        Asn1 5.3

        Fixed Bugs and Malfunctions

        Improvements and New Features

        • Specs have been added to all asn1ct API functions.

          Own Id: OTP-18804 Aux Id: PR-7738

        • The documentation has been migrated to use Markdown and ExDoc.

          Own Id: OTP-18955 Aux Id: PR-8026

        • The jer (JSON Encoding Rules) for ASN.1 now use the new json module for encoding and decoding JSON. Thus, there is no longer any need for an external JSON library.

          Own Id: OTP-19018 Aux Id: PR-8241

        Asn1 5.2.2.1

        Fixed Bugs and Malfunctions

        • The ASN.1 compiler could generate code that would cause Dialyzer with the unmatched_returns option to emit warnings.

          Own Id: OTP-19638 Aux Id: GH-9841, PR-9846

        Asn1 5.2.2

        Fixed Bugs and Malfunctions

        • An ASN.1 module that contains named BIT STRING values would fail to compiled if both the BER and JER back-ends were enabled.

          Own Id: OTP-19039 Aux Id: GH-8291, PR-8297

        Asn1 5.2.1

        Fixed Bugs and Malfunctions

        • Fix benign warning from gcc 11 about mismatching call to free().

          Own Id: OTP-18844

        Asn1 5.2

        Fixed Bugs and Malfunctions

        • The ASN.1 compiler would ignore a constraint such as (SIZE (1..4), ...), causing incorrect behavior of the encoding and decoding function for the PER and UPER backends. Corrected to handle the constraint in the same way as (SIZE (1..4, ...)).

          Own Id: OTP-18729 Aux Id: PR-7575

        Improvements and New Features

        • The JER backend has been internally refactored in a way that is compatible for /usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1_getting_started.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2617)) --- old//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1_getting_started.html 2026-08-21 04:00:18.685289957 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1_getting_started.html 2026-08-21 04:00:18.685289957 +0000 @@ -101,37 +101,37 @@ the syntax is correct and that the text represents proper ASN.1 code before generating an abstract syntax tree. The code generator then uses the abstract syntax tree to generate code.

          The generated Erlang files are placed in the current directory or in the -directory specified with option {outdir,Dir}.

          The compiler can be called from the Erlang shell like this:

          1> asn1ct:compile("People", [ber]).
          -ok

          Option verbose can be added to get information about the generated files:

          2> asn1ct:compile("People", [ber,verbose]).
          +directory specified with option {outdir,Dir}.

          The compiler can be called from the Erlang shell like this:

          1> asn1ct:compile("People", [ber]).
          +ok

          Option verbose can be added to get information about the generated files:

          2> asn1ct:compile("People", [ber,verbose]).
           Erlang ASN.1 compiling "People.asn"
          ---{generated,"People.asn1db"}--
          ---{generated,"People.hrl"}--
          ---{generated,"People.erl"}--
          +--{generated,"People.asn1db"}--
          +--{generated,"People.hrl"}--
          +--{generated,"People.erl"}--
           ok

          ASN.1 module People is now accepted and the abstract syntax tree is saved in file People.asn1db. The generated Erlang code is compiled using the Erlang compiler and loaded into the Erlang runtime system. There is now an API for -encode/2 and decode/2 in module People, which is called like this:

          'People':encode(<Type name>, <Value>)

          or:

          'People':decode(<Type name>, <Value>)

          Assume that there is a network application that receives instances of the ASN.1 +encode/2 and decode/2 in module People, which is called like this:

          'People':encode(<Type name>, <Value>)

          or:

          'People':decode(<Type name>, <Value>)

          Assume that there is a network application that receives instances of the ASN.1 defined type Person, modifies, and sends them back again:

          receive
          -   {Port,{data,Bytes}} ->
          -       case 'People':decode('Person',Bytes) of
          -           {ok,P} ->
          -               {ok,Answer} = 'People':encode('Person',mk_answer(P)),
          -               Port ! {self(),{command,Answer}};
          -           {error,Reason} ->
          -               exit({error,Reason})
          +   {Port,{data,Bytes}} ->
          +       case 'People':decode('Person',Bytes) of
          +           {ok,P} ->
          +               {ok,Answer} = 'People':encode('Person',mk_answer(P)),
          +               Port ! {self(),{command,Answer}};
          +           {error,Reason} ->
          +               exit({error,Reason})
                  end
               end,

          In this example, a series of bytes is received from an external source and the bytes are then decoded into a valid Erlang term. This was achieved with the call 'People':decode('Person',Bytes), which returned an Erlang value of the ASN.1 type Person. Then an answer was constructed and encoded using 'People':encode('Person',Answer), which takes an instance of a defined ASN.1 -type and transforms it to a binary according to the BER or PER encoding rules.

          The encoder and decoder can also be run from the shell:

          2> Rockstar = {'Person',"Some Name",roving,50}.
          -{'Person',"Some Name",roving,50}
          -3> {ok,Bin} = 'People':encode('Person',Rockstar).
          -{ok,<<243,17,19,9,83,111,109,101,32,78,97,109,101,2,1,2,
          -      2,1,50>>}
          -4> {ok,Person} = 'People':decode('Person',Bin).
          -{ok,{'Person',"Some Name",roving,50}}

          Module Dependencies

          It is common that ASN.1 modules import defined types, values, and other entities +type and transforms it to a binary according to the BER or PER encoding rules.

          The encoder and decoder can also be run from the shell:

          2> Rockstar = {'Person',"Some Name",roving,50}.
          +{'Person',"Some Name",roving,50}
          +3> {ok,Bin} = 'People':encode('Person',Rockstar).
          +{ok,<<243,17,19,9,83,111,109,101,32,78,97,109,101,2,1,2,
          +      2,1,50>>}
          +4> {ok,Person} = 'People':decode('Person',Bin).
          +{ok,{'Person',"Some Name",roving,50}}

          Module Dependencies

          It is common that ASN.1 modules import defined types, values, and other entities from another ASN.1 module.

          Earlier versions of the ASN.1 compiler required that modules that were imported from had to be compiled before the module that imported. This caused problems when ASN.1 modules had circular dependencies.

          Referenced modules are now parsed when the compiler finds an entity that is @@ -172,16 +172,16 @@ module and the NIF library in asn1/priv_dir are needed at runtime.

          By calling function info/0 in a generated module, you get information about which compiler options were used.

          Special Decode Functionality for JSON Encoding Rules (JER)

          When using the JSON encoding rules, it is possible to call the decode/2 function in the following way with data that has already -been decoded by json:decode/1:

          SomeModule:decode(Type, {json_decoded, Decoded}).

          Example:

          1> asn1ct:compile("People", [jer]).
          +been decoded by json:decode/1:

          SomeModule:decode(Type, {json_decoded, Decoded}).

          Example:

          1> asn1ct:compile("People", [jer]).
           ok
          -2> Rockstar = {'Person',"Vince Eclipse",roving,50}.
          -{'Person',"Vince Eclipse",roving,50}
          -3> {ok,Bin} = 'People':encode('Person', Rockstar).
          -{ok,<<"{\"name\":\"Vince Eclipse\",\"location\":2,\"age\":50}">>}
          -4> 'People':decode('Person', Bin).
          -{ok,{'Person',"Vince Eclipse",roving,50}}
          -5> 'People':decode('Person', {json_decoded,json:decode(Bin)}).
          -{ok,{'Person',"Vince Eclipse",roving,50}}
          +2> Rockstar = {'Person',"Vince Eclipse",roving,50}.
          +{'Person',"Vince Eclipse",roving,50}
          +3> {ok,Bin} = 'People':encode('Person', Rockstar).
          +{ok,<<"{\"name\":\"Vince Eclipse\",\"location\":2,\"age\":50}">>}
          +4> 'People':decode('Person', Bin).
          +{ok,{'Person',"Vince Eclipse",roving,50}}
          +5> 'People':decode('Person', {json_decoded,json:decode(Bin)}).
          +{ok,{'Person',"Vince Eclipse",roving,50}}
           

          Errors

          Errors detected at compile-time are displayed on the screen together with line numbers indicating where in the source file the respective error was detected. If no errors are found, an Erlang ASN.1 module is created.

          The runtime encoders and decoders execute within a catch and return {ok, Data} @@ -199,30 +199,30 @@ to manually add tags to certain constructs in order for the ASN.1 specification to be valid. Example of an old-style specification:

          Tags DEFINITIONS ::=
           BEGIN
          -  Afters ::= CHOICE { cheese [0] IA5String,
          -                      dessert [1] IA5String }
          +  Afters ::= CHOICE { cheese [0] IA5String,
          +                      dessert [1] IA5String }
           END

          Without the tags (the numbers in square brackets) the ASN.1 compiler refused to compile the file.

          In 1994 the global tagging mode AUTOMATIC TAGS was introduced. By putting AUTOMATIC TAGS in the module header, the ASN.1 compiler automatically adds tags when needed. The following is the same specification in AUTOMATIC TAGS mode:

          Tags DEFINITIONS AUTOMATIC TAGS ::=
           BEGIN
          -  Afters ::= CHOICE { cheese IA5String,
          -                      dessert IA5String }
          +  Afters ::= CHOICE { cheese IA5String,
          +                      dessert IA5String }
           END

          ASN.1 Types

          This section describes the ASN.1 types including their functionality, purpose, and how values are assigned in Erlang.

          ASN.1 has both primitive and constructed types:

          Primitive TypesConstructed Types
          BOOLEANSEQUENCE
          INTEGERSET
          REALCHOICE
          NULLSET OF and SEQUENCE OF
          ENUMERATEDANY
          BIT STRINGANY DEFINED BY
          OCTET STRINGEXTERNAL
          Character StringsEMBEDDED PDV
          OBJECT IDENTIFIERCHARACTER STRING
          Object Descriptor
          TIME Types

          Table: Supported ASN.1 Types

          Note

          The values of each ASN.1 type have their own representation in Erlang, as described in the following sections. Users must provide these values for encoding according to the representation, as shown in the following example:

          Operational ::= BOOLEAN --ASN.1 definition

          In Erlang code it can look as follows:

          Val = true,
          -{ok,Bytes} = MyModule:encode(&#href_anchor"p">, Val),

          BOOLEAN

          Booleans in ASN.1 express values that can be either TRUE or FALSE. The +{ok,Bytes} = MyModule:encode(&#href_anchor"p">, Val),

          BOOLEAN

          Booleans in ASN.1 express values that can be either TRUE or FALSE. The meanings assigned to TRUE and FALSE are outside the scope of this text.

          In ASN.1 it is possible to have:

          Operational ::= BOOLEAN

          Assigning a value to type Operational in Erlang is possible by using the following Erlang code:

          Myvar1 = true,

          Thus, in Erlang the atoms true and false are used to encode a boolean value.

          INTEGER

          An ASN.1 INTEGER is represented by an integer in Erlang.

          The concept of subtyping can be applied to integers and to other ASN.1 types. The details of subtyping are not explained here; for more information, see X.680. Various syntaxes are allowed when defining a type as an integer:

          T1 ::= INTEGER
          -T2 ::= INTEGER (-2..7)
          -T3 ::= INTEGER (0..MAX)
          -T4 ::= INTEGER (0<..MAX)
          -T5 ::= INTEGER (MIN<..-99)
          -T6 ::= INTEGER {red(0),blue(1),white(2)}

          The Erlang representation of an ASN.1 INTEGER is an integer or an atom if a +T2 ::= INTEGER (-2..7) +T3 ::= INTEGER (0..MAX) +T4 ::= INTEGER (0<..MAX) +T5 ::= INTEGER (MIN<..-99) +T6 ::= INTEGER {red(0),blue(1),white(2)}

          The Erlang representation of an ASN.1 INTEGER is an integer or an atom if a Named Number List (see T6 in the previous list) is specified.

          The following is an example of Erlang code that assigns values for the types in the previous list:

          T1value = 0,
           T2value = 6,
          @@ -247,7 +247,7 @@
           specified values, whereas an integer can have any value.

          BIT STRING

          The type BIT STRING can be used to model information that is made up of arbitrary length series of bits. It is intended to be used for selection of flags, not for binary files.

          In ASN.1, BIT STRING definitions can look as follows:

          Bits1 ::= BIT STRING
          -Bits2 ::= BIT STRING {foo(0),bar(1),gnu(2),gnome(3),punk(14)}

          The following two notations are available for representation of BIT STRING +Bits2 ::= BIT STRING {foo(0),bar(1),gnu(2),gnome(3),punk(14)}

          The following two notations are available for representation of BIT STRING values in Erlang and as input to the encode functions:

          1. A bitstring. By default, a BIT STRING with no symbolic names is decoded to an Erlang bitstring.
          2. A list of atoms corresponding to atoms in the NamedBitList in the BIT STRING definition. A BIT STRING with symbolic names is always decoded @@ -269,7 +269,7 @@ misinterpret a BIT STRING value in this format.

          OCTET STRING

          OCTET STRING is the simplest of all ASN.1 types. OCTET STRING only moves or transfers, for example, binary files or other unstructured information complying with two rules: the bytes consist of octets and encoding is not required.

          It is possible to have the following ASN.1 type definitions:

          O1 ::= OCTET STRING
          -O2 ::= OCTET STRING (SIZE(28))

          With the following example assignments in Erlang:

          O1Val = <<17,13,19,20,0,0,255,254>>,
          +O2 ::= OCTET STRING (SIZE(28))

          With the following example assignments in Erlang:

          O1Val = <<17,13,19,20,0,0,255,254>>,
           O2Val = <<"must be exactly 28 chars....">>,

          By default, an OCTET STRING is always represented as an Erlang binary. If the specification has been compiled with option legacy_erlang_types, the encode functions accept both lists and binaries, and the decode functions decode an @@ -284,11 +284,11 @@ of view, octets are very similar to character strings and are compiled in the same way.

          When PER is used, there is a significant difference in the encoding scheme for OCTET STRINGs and other strings. The constraints specified for a type -are especially important for PER, because they affect the encoding.

          Examples:

          Digs ::= NumericString (SIZE(1..3))
          -TextFile ::= IA5String (SIZE(0..64000))

          The corresponding Erlang assignments:

          DigsVal1 = "456",
          +are especially important for PER, because they affect the encoding.

          Examples:

          Digs ::= NumericString (SIZE(1..3))
          +TextFile ::= IA5String (SIZE(0..64000))

          The corresponding Erlang assignments:

          DigsVal1 = "456",
           DigsVal2 = "123",
           TextFileVal1 = "abc...xyz...",
          -TextFileVal2 = [88,76,55,44,99,121 .......... a lot of characters here ....]

          The Erlang representation for BMPString and UniversalString is either a list +TextFileVal2 = [88,76,55,44,99,121 .......... a lot of characters here ....]

          The Erlang representation for BMPString and UniversalString is either a list of ASCII values or a list of quadruples. The quadruple representation associates to the Unicode standard representation of characters. The ASCII characters are all represented by quadruples beginning with three zeros like {0,0,0,65} for @@ -297,49 +297,49 @@ in file PrimStrings.asn1:

          PrimStrings DEFINITIONS AUTOMATIC TAGS ::=
           BEGIN
              BMP ::= BMPString
          -END

          Encoding and decoding some strings:

          1> asn1ct:compile('PrimStrings', [ber]).
          +END

          Encoding and decoding some strings:

          1> asn1ct:compile('PrimStrings', [ber]).
           ok
          -2> {ok,Bytes1} = 'PrimStrings':encode('BMP', [{0,0,53,53},{0,0,45,56}]).
          -{ok,<<30,4,53,54,45,56>>}
          -3> 'PrimStrings':decode('BMP', Bytes1).
          -{ok,[{0,0,53,53},{0,0,45,56}]}
          -4> {ok,Bytes2} = 'PrimStrings':encode('BMP', [{0,0,53,53},{0,0,0,65}]).
          -{ok,<<30,4,53,53,0,65>>}
          -5> 'PrimStrings':decode('BMP', Bytes2).
          -{ok,[{0,0,53,53},65]}
          -6> {ok,Bytes3} = 'PrimStrings':encode('BMP', "BMP string").
          -{ok,<<30,20,0,66,0,77,0,80,0,32,0,115,0,116,0,114,0,105,0,110,0,103>>}
          -7> 'PrimStrings':decode('BMP', Bytes3).
          -{ok,"BMP string"}

          Type UTF8String is represented as a UTF-8 encoded binary in Erlang. Such +2> {ok,Bytes1} = 'PrimStrings':encode('BMP', [{0,0,53,53},{0,0,45,56}]). +{ok,<<30,4,53,54,45,56>>} +3> 'PrimStrings':decode('BMP', Bytes1). +{ok,[{0,0,53,53},{0,0,45,56}]} +4> {ok,Bytes2} = 'PrimStrings':encode('BMP', [{0,0,53,53},{0,0,0,65}]). +{ok,<<30,4,53,53,0,65>>} +5> 'PrimStrings':decode('BMP', Bytes2). +{ok,[{0,0,53,53},65]} +6> {ok,Bytes3} = 'PrimStrings':encode('BMP', "BMP string"). +{ok,<<30,20,0,66,0,77,0,80,0,32,0,115,0,116,0,114,0,105,0,110,0,103>>} +7> 'PrimStrings':decode('BMP', Bytes3). +{ok,"BMP string"}

      Type UTF8String is represented as a UTF-8 encoded binary in Erlang. Such binaries can be created directly using the binary syntax or by converting from a list of Unicode code points using function unicode:characters_to_binary/1.

      The following shows examples of how UTF-8 encoded binaries can be created and manipulated:

      1> Gs = "Мой маленький Гном".
      -[1052,1086,1081,32,1084,1072,1083,1077,1085,1100,1082,1080,
      - 1081,32,1043,1085,1086,1084]
      -2> Gbin = unicode:characters_to_binary(Gs).
      -<<208,156,208,190,208,185,32,208,188,208,176,208,187,208,
      +[1052,1086,1081,32,1084,1072,1083,1077,1085,1100,1082,1080,
      + 1081,32,1043,1085,1086,1084]
      /usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1_spec.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1628))
      --- old//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1_spec.html	2026-08-21 04:00:18.709290113 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1_spec.html	2026-08-21 04:00:18.709290113 +0000
      @@ -111,31 +111,31 @@
       exclusive decode is enabled. This function decodes the parts that
       were left undecoded during the exclusive decode.

    Both functions are described in the following.

    If the exclusive decode function has, for example, the name decode_exclusive and an ASN.1 encoded message Bin is to be exclusive decoded, the call is as -follows:

    {ok,ExclMessage} = 'MyModule':decode_exclusive(Bin)

    The result ExclMessage has the same structure as a +follows:

    {ok,ExclMessage} = 'MyModule':decode_exclusive(Bin)

    The result ExclMessage has the same structure as a complete decode would have, except for the parts of the top type that were not decoded. The undecoded parts are on their places in the structure on format {TypeKey,UndecodedValue}.

    Each undecoded part that is to be decoded must be fed into function -decode_part/2 as follows:

    {ok,PartMessage} = &#href_anchor"p">:decode_part(TypeKey, UndecodedValue)

    Writing an Exclusive Decode Instruction

    This instruction is written in the configuration file in the following format:

    ExclusiveDecodeInstruction = {exclusive_decode,{ModuleName,DecodeInstructions}}.
    +decode_part/2 as follows:

    {ok,PartMessage} = &#href_anchor"p">:decode_part(TypeKey, UndecodedValue)

    Writing an Exclusive Decode Instruction

    This instruction is written in the configuration file in the following format:

    ExclusiveDecodeInstruction = {exclusive_decode,{ModuleName,DecodeInstructions}}.
     
    -ModuleName = atom()
    +ModuleName = atom()
     
    -DecodeInstructions = [DecodeInstruction]+
    +DecodeInstructions = [DecodeInstruction]+
     
    -DecodeInstruction = {ExclusiveDecodeFunctionName,TypeList}
    +DecodeInstruction = {ExclusiveDecodeFunctionName,TypeList}
     
    -ExclusiveDecodeFunctionName = atom()
    +ExclusiveDecodeFunctionName = atom()
     
    -TypeList = [TopType,ElementList]
    +TypeList = [TopType,ElementList]
     
    -ElementList = [Element]+
    +ElementList = [Element]+
     
    -Element = {Name,parts} |
    -          {Name,undecoded} |
    -          {Name,ElementList}
    +Element = {Name,parts} |
    +          {Name,undecoded} |
    +          {Name,ElementList}
     
    -TopType = atom()
    +TopType = atom()
     
    -Name = atom()

    The instruction must be a valid Erlang term terminated by a dot.

    In TypeList the path from the top type to each undecoded subcomponent is +Name = atom()

    The instruction must be a valid Erlang term terminated by a dot.

    In TypeList the path from the top type to each undecoded subcomponent is described. TopType is the name of a top-level type in the ASN.1 specification. The action for each component in ElementList is described by one of:

    • {Name,parts}
    • {Name,undecoded}
    • {Name,ElementList}

    The use and effect of the actions are as follows:

    • {Name,undecoded} - Leaves the element undecoded. The type of Name can be any ASN.1 type. The value of element Name is returned as a tuple (as @@ -195,78 +195,78 @@ ['Button',[{number,undecoded}]]}]}}.

      The following figure shows the bytes of a Window:status message. The components buttonList and actions are excluded from decode. Only state and enabled are decoded when decode__Window_exclusive is called.

      Bytes of a Window:status Message

      Here follows an example of how the module. Note that option no_ok_wrapper is -used to make the example more concise.

      1> asn1ct:compile('GUI', [ber,asn1config,no_ok_wrapper]).
      +used to make the example more concise.

      1> asn1ct:compile('GUI', [ber,asn1config,no_ok_wrapper]).
       ok
      -2> rr('GUI').
      -['Action','Button','Status']
      -3> ButtonMsg = #'Button'{number=123,on=true}.
      -#'Button'{number = 123,on = true}
      -4> ButtonBytes = 'GUI':encode('Button', ButtonMsg).
      -<<48,6,128,1,123,129,1,255>>
      -5> ExclusiveMsgButton = 'GUI':decode_Button_exclusive(ButtonBytes).
      -#'Button'{number = {'Button_number',<<128,1,123>>},
      -          on = true}
      -6> {UndecKey,UndecBytes} = ExclusiveMsgButton#'Button'.number.
      -{'Button_number',<<128,1,123>>}
      -7> 'GUI':decode_part(UndecKey, UndecBytes).
      +2> rr('GUI').
      +['Action','Button','Status']
      +3> ButtonMsg = #'Button'{number=123,on=true}.
      +#'Button'{number = 123,on = true}
      +4> ButtonBytes = 'GUI':encode('Button', ButtonMsg).
      +<<48,6,128,1,123,129,1,255>>
      +5> ExclusiveMsgButton = 'GUI':decode_Button_exclusive(ButtonBytes).
      +#'Button'{number = {'Button_number',<<128,1,123>>},
      +          on = true}
      +6> {UndecKey,UndecBytes} = ExclusiveMsgButton#'Button'.number.
      +{'Button_number',<<128,1,123>>}
      +7> 'GUI':decode_part(UndecKey, UndecBytes).
       123
       8> WindowMsg =
      -{status,{'Status',35,
      -   [{'Button',3,true},
      -    {'Button',4,false},
      -    {'Button',5,true},
      -    {'Button',6,true},
      -    {'Button',7,false}],
      +{status,{'Status',35,
      +   [{'Button',3,true},
      +    {'Button',4,false},
      +    {'Button',5,true},
      +    {'Button',6,true},
      +    {'Button',7,false}],
          false,
      -   {possibleActions,[{'Action',16,{'Button',17,true}}]}}}.
      -{status,#'Status'{state = 35,
      -        buttonList = [#'Button'{number = 3,on = true},
      -                      #'Button'{number = 4,on = false},
      -                      #'Button'{number = 5,on = true},
      -                      #'Button'{number = 6,on = true},
      -                      #'Button'{number = 7,on = false}],
      +   {possibleActions,[{'Action',16,{'Button',17,true}}]}}}.
      +{status,#'Status'{state = 35,
      +        buttonList = [#'Button'{number = 3,on = true},
      +                      #'Button'{number = 4,on = false},
      +                      #'Button'{number = 5,on = true},
      +                      #'Button'{number = 6,on = true},
      +                      #'Button'{number = 7,on = false}],
               enabled = false,
      -        actions = {possibleActions,[#'Action'{number = 16,
      -                                              handle = #'Button'{number = 17,on = true}}]}}}
      -9> WindowBytes = 'GUI':encode('Window', WindowMsg).
      -<<161,65,128,1,35,161,40,48,6,128,1,3,129,1,255,48,6,128,
      -  1,4,129,1,0,48,6,128,1,5,129,...>>
      -10> {status,#'Status'{buttonList={UndecWindowKey,UndecWindowParts}}} =
      -'GUI':decode_Window_exclusive(WindowBytes).
      -{status,#'Status'{state = 35,
      -                  buttonList = {'Status_buttonList',[<<48,6,128,1,3,129,1,
      -                                                       255>>,
      -                                                     <<48,6,128,1,4,129,1,0>>,
      -                                                     <<48,6,128,1,5,129,1,255>>,
      -                                                     <<48,6,128,1,6,129,1,255>>,
      -                                                     <<48,6,128,1,7,129,1,0>>]},
      +        actions = {possibleActions,[#'Action'{number = 16,
      +                                              handle = #'Button'{number = 17,on = true}}]}}}
      +9> WindowBytes = 'GUI':encode('Window', WindowMsg).
      +<<161,65,128,1,35,161,40,48,6,128,1,3,129,1,255,48,6,128,
      +  1,4,129,1,0,48,6,128,1,5,129,...>>
      +10> {status,#'Status'{buttonList={UndecWindowKey,UndecWindowParts}}} =
      +'GUI':decode_Window_exclusive(WindowBytes).
      +{status,#'Status'{state = 35,
      +                  buttonList = {'Status_buttonList',[<<48,6,128,1,3,129,1,
      +                                                       255>>,
      +                                                     <<48,6,128,1,4,129,1,0>>,
      +                                                     <<48,6,128,1,5,129,1,255>>,
      +                                                     <<48,6,128,1,6,129,1,255>>,
      +                                                     <<48,6,128,1,7,129,1,0>>]},
                         enabled = false,
      -                  actions = {'Status_actions',<<163,15,160,13,48,11,128,
      +                  actions = {'Status_actions',<<163,15,160,13,48,11,128,
                                                       1,16,161,6,128,1,17,129,
      -                                                1,255>>}}}
      -11> 'GUI':decode_part(UndecWindowKey, UndecWindowParts).
      -[#'Button'{number = 3,on = true},
      - #'Button'{number = 4,on = false},
      - #'Button'{number = 5,on = true},
      - #'Button'{number = 6,on = true},
      - #'Button'{number = 7,on = false}]
      -12> 'GUI':decode_part(UndecWindowKey, hd(UndecWindowParts)).
      -#'Button'{number = 3,on = true}
      -13> {status,#'Status'{actions={ChoiceKey,ChoiceUndec}}} = v(10).
      -{status,#'Status'{state = 35,
      -                  buttonList = {'Status_buttonList',[<<48,6,128,1,3,129,1,
      -                                                       255>>,
      -                                                     <<48,6,128,1,4,129,1,0>>,
      -                                                     <<48,6,128,1,5,129,1,255>>,
      -                                                     <<48,6,128,1,6,129,1,255>>,
      -                                                     <<48,6,128,1,7,129,1,0>>]},
      +                                                1,255>>}}}
      +11> 'GUI':decode_part(UndecWindowKey, UndecWindowParts).
      +[#'Button'{number = 3,on = true},
      + #'Button'{number = 4,on = false},
      + #'Button'{number = 5,on = true},
      + #'Button'{number = 6,on = true},
      + #'Button'{number = 7,on = false}]
      +12> 'GUI':decode_part(UndecWindowKey, hd(UndecWindowParts)).
      +#'Button'{number = 3,on = true}
      +13> {status,#'Status'{actions={ChoiceKey,ChoiceUndec}}} = v(10).
      +{status,#'Status'{state = 35,
      +                  buttonList = {'Status_buttonList',[<<48,6,128,1,3,129,1,
      +                                                       255>>,
      +                                                     <<48,6,128,1,4,129,1,0>>,
      +                                                     <<48,6,128,1,5,129,1,255>>,
      +                                                     <<48,6,128,1,6,129,1,255>>,
      +                                                     <<48,6,128,1,7,129,1,0>>]},
                         enabled = false,
      -                  actions = {'Status_actions',<<163,15,160,13,48,11,128,
      +                  actions = {'Status_actions',<<163,15,160,13,48,11,128,
                                                       1,16,161,6,128,1,17,129,
      -                                                1,255>>}}}
      -14> 'GUI':decode_part(ChoiceKey, ChoiceUndec).
      -{possibleActions,[#'Action'{number = 16,
      -                            handle = #'Button'{number = 17,on = true}}]}

      Selective Decode

      Selective decode decodes a single subtype of a constructed value. This is the + 1,255>>}}} +14> 'GUI':decode_part(ChoiceKey, ChoiceUndec). +{possibleActions,[#'Action'{number = 16, + handle = #'Button'{number = 17,on = true}}]}

      Selective Decode

      Selective decode decodes a single subtype of a constructed value. This is the fastest method to extract a subvalue. Selective decode is typically used when one want to inspect, for example, a version number to be able to decide how to handle the entire value.

      Procedure

      To perform a selective decode:

      • Step 1: Include the following instructions in the configuration file:

        • The name of the user function
        • The name of the ASN.1 specification
        • A notation that tells which part of the type to be decoded
      • Step 2: Compile with the additional option asn1config. The compiler @@ -279,23 +279,23 @@ {selective_decode,{'ModuleName',[{selected_decode_Window,TypeList}]}} do the selective decode by {ok,Result} = 'ModuleName':selected_decode_Window(EncodedBinary).

        Writing a Selective Decode Instruction

        One or more selective decode functions can be described in a configuration file. -Use the following notation:

        SelectiveDecodeInstruction = {selective_decode,{ModuleName,DecodeInstructions}}.
        +Use the following notation:

        SelectiveDecodeInstruction = {selective_decode,{ModuleName,DecodeInstructions}}.
         
        -ModuleName = atom()
        +ModuleName = atom()
         
        -DecodeInstructions = [DecodeInstruction]+
        /usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1ct.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1304))
        --- old//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1ct.html	2026-08-21 04:00:18.733290269 +0000
        +++ new//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/asn1ct.html	2026-08-21 04:00:18.733290269 +0000
        @@ -460,9 +460,9 @@
         mostly work for old specifications based on the 1997 standard for ASN.1, but
         not for most modern-style applications. Another limitation is that the test
         functions may not work if options that change code generations strategies such
        -as the options macro_name_prefix and record_name_prefix have been used.

        • test/1 iterates over all types in Module.
        • test/2 tests type Type with a random value.
        • test/3 tests type Type with Value.

        Schematically, the following occurs for each type in the module:

        {ok, Value} = asn1ct:value(Module, Type),
        -{ok, Bytes} = Module:encode(Type, Value),
        -{ok, Value} = Module:decode(Type, Bytes).

        The test functions use the *.asn1db files for all included modules. If they +as the options macro_name_prefix and record_name_prefix have been used.

        • test/1 iterates over all types in Module.
        • test/2 tests type Type with a random value.
        • test/3 tests type Type with Value.

        Schematically, the following occurs for each type in the module:

        {ok, Value} = asn1ct:value(Module, Type),
        +{ok, Bytes} = Module:encode(Type, Value),
        +{ok, Value} = Module:decode(Type, Bytes).

        The test functions use the *.asn1db files for all included modules. If they are located in a different directory than the current working directory, use the include option to add paths. This is only needed when automatically generating values. For static values using Value no options are needed.

        /usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (15479)) --- old//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/notes.html 2026-08-21 04:00:18.760290445 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/asn1-5.4.3/doc/html/notes.html 2026-08-21 04:00:18.760290445 +0000 @@ -89,7 +89,7 @@ -

        This document describes the changes made to the asn1 application.

        Asn1 5.4.3

        Improvements and New Features

        • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

          A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

          make release_docs places the documentation in the released code under the doc folder.

          make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

          The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

          Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

          Improves the source Software-Bill-of-Materials

          • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
          • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
          • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

          Own Id: OTP-19886 Aux Id: PR-10434

        Asn1 5.4.2

        Fixed Bugs and Malfunctions

        • Decoding a constrained BIT STRING using JER was broken.

          Own Id: OTP-19681 Aux Id: PR-9949

        • NIFs and linked-in drivers are now loadable when running in an Erlang source tree on Windows.

          Own Id: OTP-19686 Aux Id: PR-9969

        Asn1 5.4.1

        Fixed Bugs and Malfunctions

        • The ASN.1 compiler could generate code that would cause Dialyzer with the unmatched_returns option to emit warnings.

          Own Id: OTP-19638 Aux Id: GH-9841, PR-9846

        Asn1 5.4

        Fixed Bugs and Malfunctions

        • The undec_rest option would be ignored in generated functions for exclusive decode. The option is now respected, meaning that the return value from such functions are now three-tuples instead of a two-tuples.

          POTENTIAL INCOMPATIBILITY

          Own Id: OTP-19290 Aux Id: PR-8798

        Improvements and New Features

        • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

          Own Id: OTP-19575 Aux Id: PR-9670

        • The ancient ASN.1 modules used in public_key has been replaced with more modern versions, but we have strived to keep the documented Erlang API for the public_key application compatible.

          POTENTIAL INCOMPATIBILITY

          Own Id: OTP-19612 Aux Id: PR-9774

        Asn1 5.3.4.2

        Fixed Bugs and Malfunctions

        • Decoding a constrained BIT STRING using JER was broken.

          Own Id: OTP-19681 Aux Id: PR-9949

        Asn1 5.3.4.1

        Fixed Bugs and Malfunctions

        • The ASN.1 compiler could generate code that would cause Dialyzer with the unmatched_returns option to emit warnings.

          Own Id: OTP-19638 Aux Id: GH-9841, PR-9846

        Asn1 5.3.4

        Fixed Bugs and Malfunctions

        • Negative REAL numbers greater than -1 would be incorrectly encoded (the minus sign would be lost).

          Own Id: OTP-19567 Aux Id: ERIERL-1214, PR-9658

        Asn1 5.3.3

        Fixed Bugs and Malfunctions

        • The JER backend will now include the SIZE constraint in the type info for OCTET STRINGs, and a SIZE constraint with a range will now be included for BIT STRINGs. This does not change the actual encoding or decoding of JER, but can be useful for tools.

          Own Id: OTP-19542 Aux Id: ERIERL-1204, PR-9588

        Improvements and New Features

        • When using the JSON encoding rules, it is now possible to call the decode/2 function in the following way with data that has already been decoded by json:decode/1:

          SomeModule:decode(Type, {json_decoded, Decoded}).

          Own Id: OTP-19547 Aux Id: ERIERL-1206, PR-9611

        Asn1 5.3.2

        Fixed Bugs and Malfunctions

        • Multiple bugs in decoding of the REAL type has been eliminated. Also, the documentation for REAL has been updated to mention the special values 0, PLUS-INFINITY, and MINUS-INFINITY.

          Own Id: OTP-19504 Aux Id: GH-9096, PR-9469

        Asn1 5.3.1

        Fixed Bugs and Malfunctions

        • Fixed a cosmetic but harmless issue with the ASN.1 compiler passing on the undec_rest option to the Erlang compiler.

          Own Id: OTP-19218 Aux Id: GH-8779, PR-8781

        Asn1 5.3

        Fixed Bugs and Malfunctions

        Improvements and New Features

        • Specs have been added to all asn1ct API functions.

          Own Id: OTP-18804 Aux Id: PR-7738

        • The documentation has been migrated to use Markdown and ExDoc.

          Own Id: OTP-18955 Aux Id: PR-8026

        • The jer (JSON Encoding Rules) for ASN.1 now use the new json module for encoding and decoding JSON. Thus, there is no longer any need for an external JSON library.

          Own Id: OTP-19018 Aux Id: PR-8241

        Asn1 5.2.2.1

        Fixed Bugs and Malfunctions

        • The ASN.1 compiler could generate code that would cause Dialyzer with the unmatched_returns option to emit warnings.

          Own Id: OTP-19638 Aux Id: GH-9841, PR-9846

        Asn1 5.2.2

        Fixed Bugs and Malfunctions

        • An ASN.1 module that contains named BIT STRING values would fail to compiled if both the BER and JER back-ends were enabled.

          Own Id: OTP-19039 Aux Id: GH-8291, PR-8297

        Asn1 5.2.1

        Fixed Bugs and Malfunctions

        • Fix benign warning from gcc 11 about mismatching call to free().

          Own Id: OTP-18844

        Asn1 5.2

        Fixed Bugs and Malfunctions

        • The ASN.1 compiler would ignore a constraint such as (SIZE (1..4), ...), +

          This document describes the changes made to the asn1 application.

          Asn1 5.4.3

          Improvements and New Features

          • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

            A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

            make release_docs places the documentation in the released code under the doc folder.

            make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

            The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

            Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

            Improves the source Software-Bill-of-Materials

            • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
            • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
            • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

            Own Id: OTP-19886 Aux Id: PR-10434

          Asn1 5.4.2

          Fixed Bugs and Malfunctions

          • Decoding a constrained BIT STRING using JER was broken.

            Own Id: OTP-19681 Aux Id: PR-9949

          • NIFs and linked-in drivers are now loadable when running in an Erlang source tree on Windows.

            Own Id: OTP-19686 Aux Id: PR-9969

          Asn1 5.4.1

          Fixed Bugs and Malfunctions

          • The ASN.1 compiler could generate code that would cause Dialyzer with the unmatched_returns option to emit warnings.

            Own Id: OTP-19638 Aux Id: GH-9841, PR-9846

          Asn1 5.4

          Fixed Bugs and Malfunctions

          • The undec_rest option would be ignored in generated functions for exclusive decode. The option is now respected, meaning that the return value from such functions are now three-tuples instead of a two-tuples.

            POTENTIAL INCOMPATIBILITY

            Own Id: OTP-19290 Aux Id: PR-8798

          Improvements and New Features

          • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

            Own Id: OTP-19575 Aux Id: PR-9670

          • The ancient ASN.1 modules used in public_key has been replaced with more modern versions, but we have strived to keep the documented Erlang API for the public_key application compatible.

            POTENTIAL INCOMPATIBILITY

            Own Id: OTP-19612 Aux Id: PR-9774

          Asn1 5.3.4.2

          Fixed Bugs and Malfunctions

          • Decoding a constrained BIT STRING using JER was broken.

            Own Id: OTP-19681 Aux Id: PR-9949

          Asn1 5.3.4.1

          Fixed Bugs and Malfunctions

          • The ASN.1 compiler could generate code that would cause Dialyzer with the unmatched_returns option to emit warnings.

            Own Id: OTP-19638 Aux Id: GH-9841, PR-9846

          Asn1 5.3.4

          Fixed Bugs and Malfunctions

          • Negative REAL numbers greater than -1 would be incorrectly encoded (the minus sign would be lost).

            Own Id: OTP-19567 Aux Id: ERIERL-1214, PR-9658

          Asn1 5.3.3

          Fixed Bugs and Malfunctions

          • The JER backend will now include the SIZE constraint in the type info for OCTET STRINGs, and a SIZE constraint with a range will now be included for BIT STRINGs. This does not change the actual encoding or decoding of JER, but can be useful for tools.

            Own Id: OTP-19542 Aux Id: ERIERL-1204, PR-9588

          Improvements and New Features

          • When using the JSON encoding rules, it is now possible to call the decode/2 function in the following way with data that has already been decoded by json:decode/1:

            SomeModule:decode(Type, {json_decoded, Decoded}).

            Own Id: OTP-19547 Aux Id: ERIERL-1206, PR-9611

          Asn1 5.3.2

          Fixed Bugs and Malfunctions

          • Multiple bugs in decoding of the REAL type has been eliminated. Also, the documentation for REAL has been updated to mention the special values 0, PLUS-INFINITY, and MINUS-INFINITY.

            Own Id: OTP-19504 Aux Id: GH-9096, PR-9469

          Asn1 5.3.1

          Fixed Bugs and Malfunctions

          • Fixed a cosmetic but harmless issue with the ASN.1 compiler passing on the undec_rest option to the Erlang compiler.

            Own Id: OTP-19218 Aux Id: GH-8779, PR-8781

          Asn1 5.3

          Fixed Bugs and Malfunctions

          Improvements and New Features

          • Specs have been added to all asn1ct API functions.

            Own Id: OTP-18804 Aux Id: PR-7738

          • The documentation has been migrated to use Markdown and ExDoc.

            Own Id: OTP-18955 Aux Id: PR-8026

          • The jer (JSON Encoding Rules) for ASN.1 now use the new json module for encoding and decoding JSON. Thus, there is no longer any need for an external JSON library.

            Own Id: OTP-19018 Aux Id: PR-8241

          Asn1 5.2.2.1

          Fixed Bugs and Malfunctions

          • The ASN.1 compiler could generate code that would cause Dialyzer with the unmatched_returns option to emit warnings.

            Own Id: OTP-19638 Aux Id: GH-9841, PR-9846

          Asn1 5.2.2

          Fixed Bugs and Malfunctions

          • An ASN.1 module that contains named BIT STRING values would fail to compiled if both the BER and JER back-ends were enabled.

            Own Id: OTP-19039 Aux Id: GH-8291, PR-8297

          Asn1 5.2.1

          Fixed Bugs and Malfunctions

          • Fix benign warning from gcc 11 about mismatching call to free().

            Own Id: OTP-18844

          Asn1 5.2

          Fixed Bugs and Malfunctions

          • The ASN.1 compiler would ignore a constraint such as (SIZE (1..4), ...), causing incorrect behavior of the encoding and decoding function for the PER and UPER backends. Corrected to handle the constraint in the same way as (SIZE (1..4, ...)).

            Own Id: OTP-18729 Aux Id: PR-7575

          Improvements and New Features

          • The JER backend has been internally refactored in a way that is compatible for /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/basics_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/basics_chapter.html 2026-08-21 04:00:18.781290582 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/basics_chapter.html 2026-08-21 04:00:18.781290582 +0000 @@ -155,15 +155,15 @@ the reason for termination is. If you use Erlang pattern matching effectively, you can take advantage of this property. The result is concise and readable test case functions that look much more like scripts than actual programs. A simple -example:

            session(_Config) ->
            -    {started,ServerId} = my_server:start(),
            -    {clients,[]} = my_server:get_clients(ServerId),
            -    MyId = self(),
            -    connected = my_server:connect(ServerId, MyId),
            -    {clients,[MyId]} = my_server:get_clients(ServerId),
            -    disconnected = my_server:disconnect(ServerId, MyId),
            -    {clients,[]} = my_server:get_clients(ServerId),
            -    stopped = my_server:stop(ServerId).

            As a test suite runs, all information (including output to stdout) is recorded +example:

            session(_Config) ->
            +    {started,ServerId} = my_server:start(),
            +    {clients,[]} = my_server:get_clients(ServerId),
            +    MyId = self(),
            +    connected = my_server:connect(ServerId, MyId),
            +    {clients,[MyId]} = my_server:get_clients(ServerId),
            +    disconnected = my_server:disconnect(ServerId, MyId),
            +    {clients,[]} = my_server:get_clients(ServerId),
            +    stopped = my_server:stop(ServerId).

            As a test suite runs, all information (including output to stdout) is recorded in many different log files. A minimum of information is displayed in the user console (only start and stop information, plus a note for each failed test case).

            The result from each test case is recorded in a dedicated HTML log file, created /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/basics_chapter.xhtml differs (HTML document, ASCII text, with very long lines (650)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/basics_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/basics_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -83,15 +83,15 @@ the reason for termination is. If you use Erlang pattern matching effectively, you can take advantage of this property. The result is concise and readable test case functions that look much more like scripts than actual programs. A simple -example:

            session(_Config) ->
            -    {started,ServerId} = my_server:start(),
            -    {clients,[]} = my_server:get_clients(ServerId),
            -    MyId = self(),
            -    connected = my_server:connect(ServerId, MyId),
            -    {clients,[MyId]} = my_server:get_clients(ServerId),
            -    disconnected = my_server:disconnect(ServerId, MyId),
            -    {clients,[]} = my_server:get_clients(ServerId),
            -    stopped = my_server:stop(ServerId).

            As a test suite runs, all information (including output to stdout) is recorded +example:

            session(_Config) ->
            +    {started,ServerId} = my_server:start(),
            +    {clients,[]} = my_server:get_clients(ServerId),
            +    MyId = self(),
            +    connected = my_server:connect(ServerId, MyId),
            +    {clients,[MyId]} = my_server:get_clients(ServerId),
            +    disconnected = my_server:disconnect(ServerId, MyId),
            +    {clients,[]} = my_server:get_clients(ServerId),
            +    stopped = my_server:stop(ServerId).

            As a test suite runs, all information (including output to stdout) is recorded in many different log files. A minimum of information is displayed in the user console (only start and stop information, plus a note for each failed test case).

            The result from each test case is recorded in a dedicated HTML log file, created /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/config_file_chapter.xhtml differs (HTML document, ASCII text, with very long lines (1269)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/config_file_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/config_file_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -22,8 +22,8 @@ configuration files or strings that Common Test reads before the start of a test run. External configuration data makes it possible to change test properties without modifying the test suites using the data. Examples of -configuration data follows:

            • Addresses to the test plant or other instruments
            • User login information
            • Names of files needed by the test
            • Names of programs to be executed during the test
            • Any other variable needed by the test

            Syntax

            A configuration file can contain any number of elements of the type:

            {CfgVarName,Value}.

            where

            CfgVarName = atom()
            -Value = term() | [{CfgVarName,Value}]

            Requiring and Reading Configuration Data

            In a test suite, one must require that a configuration variable (CfgVarName +configuration data follows:

            • Addresses to the test plant or other instruments
            • User login information
            • Names of files needed by the test
            • Names of programs to be executed during the test
            • Any other variable needed by the test

            Syntax

            A configuration file can contain any number of elements of the type:

            {CfgVarName,Value}.

            where

            CfgVarName = atom()
            +Value = term() | [{CfgVarName,Value}]

            Requiring and Reading Configuration Data

            In a test suite, one must require that a configuration variable (CfgVarName in the previous definition) exists before attempting to read the associated value in a test case or configuration function.

            require is an assert statement, which can be part of the Test Suite Information Function or @@ -44,13 +44,13 @@ any number of alias names, but each name must be unique within the same test suite. The two main uses for alias names follows:

            • To identify connections (described later).
            • To help adapt configuration data to a test suite (or test case) and improve readability.

            To read the value of a configuration variable, use function -get_config/1,2,3.

            Example:

            suite() ->
            -    [{require, domain, 'CONN_SPEC_DNS_SUFFIX'}].
            +get_config/1,2,3.

            Example:

            suite() ->
            +    [{require, domain, 'CONN_SPEC_DNS_SUFFIX'}].
             
             ...
             
            -testcase(Config) ->
            -    Domain = ct:get_config(domain),
            +testcase(Config) ->
            +    Domain = ct:get_config(domain),
                 ...

            Using Configuration Variables Defined in Multiple Files

            If a configuration variable is defined in multiple files and you want to access all possible values, use function ct:get_config/3 and specify all in the options list. The values are then returned in a list and the order of the @@ -99,11 +99,11 @@ </ftp_host> <lm_directory>"/test/loadmodules"</lm_directory> </config>

            Once read, this file produces the same configuration variables as the following -text file:

            {ftp_host, [{ftp,"targethost"},
            -            {username,"tester"},
            -            {password,"letmein"}]}.
            +text file:

            {ftp_host, [{ftp,"targethost"},
            +            {username,"tester"},
            +            {password,"letmein"}]}.
             
            -{lm_directory, "/test/loadmodules"}.

            Implement a User-Specific Handler

            The user-specific handler can be written to handle special configuration file +{lm_directory, "/test/loadmodules"}.

            Implement a User-Specific Handler

            The user-specific handler can be written to handle special configuration file formats. The parameter can be either file names or configuration strings (the empty list is valid).

            The callback module implementing the handler is responsible for checking the correctness of configuration strings.

            To validate the configuration strings, the callback module is to have function @@ -116,130 +116,130 @@ data being reloaded during test execution. The input argument is the same as for function check_parameter/1.

            The return value is to be either of the following:

            • {ok, Config} - if the configuration variables are read successfully.
            • {error, {Error, ErrorDetails}} - if the callback module fails to proceed with the specified configuration parameters.

            Config is the proper Erlang key-value list, with possible key-value sublists -as values, like the earlier configuration file example:

            [{ftp_host, [{ftp, "targethost"}, {username, "tester"}, {password, "letmein"}]},
            - {lm_directory, "/test/loadmodules"}]

            Examples of Configuration Data Handling

            A configuration file for using the FTP client to access files on a remote host -can look as follows:

            {ftp_host, [{ftp,"targethost"},
            -            {username,"tester"},
            -            {password,"letmein"}]}.
            +as values, like the earlier configuration file example:

            [{ftp_host, [{ftp, "targethost"}, {username, "tester"}, {password, "letmein"}]},
            + {lm_directory, "/test/loadmodules"}]

            Examples of Configuration Data Handling

            A configuration file for using the FTP client to access files on a remote host +can look as follows:

            {ftp_host, [{ftp,"targethost"},
            +            {username,"tester"},
            +            {password,"letmein"}]}.
             
            -{lm_directory, "/test/loadmodules"}.

            The XML version shown earlier can also be used, but it is to be explicitly +{lm_directory, "/test/loadmodules"}.

            The XML version shown earlier can also be used, but it is to be explicitly specified that the ct_config_xml callback module is to be used by Common Test.

            The following is an example of how to assert that the configuration data is -available and can be used for an FTP session:

            init_per_testcase(ftptest, Config) ->
            -    {ok,_} = ct_ftp:open(ftp),
            +available and can be used for an FTP session:

            init_per_testcase(ftptest, Config) ->
            +    {ok,_} = ct_ftp:open(ftp),
                 Config.
             
            -end_per_testcase(ftptest, _Config) ->
            -    ct_ftp:close(ftp).
            +end_per_testcase(ftptest, _Config) ->
            +    ct_ftp:close(ftp).
             
            -ftptest() ->
            -    [{require,ftp,ftp_host},
            -     {require,lm_directory}].
            -
            -ftptest(Config) ->
            -    Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
            -    Local = filename:join(proplists:get_value(priv_dir,Config), "loadmodule"),
            -    ok = ct_ftp:recv(ftp, Remote, Local),
            +ftptest() ->
            +    [{require,ftp,ftp_host},
            +     {require,lm_directory}].
            +
            +ftptest(Config) ->
            +    Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
            +    Local = filename:join(proplists:get_value(priv_dir,Config), "loadmodule"),
            +    ok = ct_ftp:recv(ftp, Remote, Local),
                 ...

            The following is an example of how the functions in the previous example can be -rewritten if it is necessary to open multiple connections to the FTP server:

            init_per_testcase(ftptest, Config) ->
            -    {ok,Handle1} = ct_ftp:open(ftp_host),
            -    {ok,Handle2} = ct_ftp:open(ftp_host),
            -    [{ftp_handles,[Handle1,Handle2]} | Config].
            -
            -end_per_testcase(ftptest, Config) ->
            -    lists:foreach(fun(Handle) -> ct_ftp:close(Handle) end,
            -                  proplists:get_value(ftp_handles,Config)).
            -
            -ftptest() ->
            -    [{require,ftp_host},
            -     {require,lm_directory}].
            -
            -ftptest(Config) ->
            -    Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
            -    Local = filename:join(proplists:get_value(priv_dir,Config), "loadmodule"),
            -    [Handle | MoreHandles] = proplists:get_value(ftp_handles,Config),
            -    ok = ct_ftp:recv(Handle, Remote, Local),
            +rewritten if it is necessary to open multiple connections to the FTP server:

            init_per_testcase(ftptest, Config) ->
            +    {ok,Handle1} = ct_ftp:open(ftp_host),
            +    {ok,Handle2} = ct_ftp:open(ftp_host),
            +    [{ftp_handles,[Handle1,Handle2]} | Config].
            +
            +end_per_testcase(ftptest, Config) ->
            +    lists:foreach(fun(Handle) -> ct_ftp:close(Handle) end,
            +                  proplists:get_value(ftp_handles,Config)).
            +
            +ftptest() ->
            +    [{require,ftp_host},
            +     {require,lm_directory}].
            +
            +ftptest(Config) ->
            +    Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
            +    Local = filename:join(proplists:get_value(priv_dir,Config), "loadmodule"),
            +    [Handle | MoreHandles] = proplists:get_value(ftp_handles,Config),
            +    ok = ct_ftp:recv(Handle, Remote, Local),
                 ...

            Example of User-Specific Configuration Handler

            A simple configuration handling driver, asking an external server for -configuration data, can be implemented as follows:

            -module(config_driver).
            --export([read_config/1, check_parameter/1]).
            +configuration data, can be implemented as follows:

            -module(config_driver).
            +-export([read_config/1, check_parameter/1]).
             
            -read_config(ServerName)->
            -    ServerModule = list_to_atom(ServerName),
            -    ServerModule:start(),
            -    ServerModule:get_config().
            -
            -check_parameter(ServerName)->
            -    ServerModule = list_to_atom(ServerName),
            -    case code:is_loaded(ServerModule) of
            -        {file, _}->
            -            {ok, {config, ServerName}};
            +read_config(ServerName)->
            +    ServerModule = list_to_atom(ServerName),
            +    ServerModule:start(),
            +    ServerModule:get_config().
            +
            +check_parameter(ServerName)->
            +    ServerModule = list_to_atom(ServerName),
            +    case code:is_loaded(ServerModule) of
            +        {file, _}->
            +            {ok, {config, ServerName}};
                     false->
            -            case code:load_file(ServerModule) of
            -                {module, ServerModule}->
            -                    {ok, {config, ServerName}};
            -                {error, nofile}->
            -                    {error, {wrong_config, "File not found: " ++ ServerName ++ ".beam"}}
            +            case code:load_file(ServerModule) of
            +                {module, ServerModule}->
            +                    {ok, {config, ServerName}};
            +                {error, nofile}->
            +                    {error, {wrong_config, "File not found: " ++ ServerName ++ ".beam"}}
                         end
                 end.

            The configuration string for this driver can be config_server, if the config_server.erl module that follows is compiled and exists in the code path -during test execution:

            -module(config_server).
            --export([start/0, stop/0, init/1, get_config/0, loop/0]).
            +during test execution:

            -module(config_server).
            +-export([start/0, stop/0, init/1, get_config/0, loop/0]).
             
            --define(REGISTERED_NAME, ct_test_config_server).
            +-define(REGISTERED_NAME, ct_test_config_server).
             
            -start()->
            -    case whereis(?REGISTERED_NAME) of
            +start()->
            +    case whereis(?REGISTERED_NAME) of
                     undefined->
            -            spawn(?MODULE, init, [?REGISTERED_NAME]),
            -            wait();
            +            spawn(?MODULE, init, [?REGISTERED_NAME]),
            +            wait();
                     _Pid->
                     ok
                 end,
                 ?REGISTERED_NAME.
             
            -init(Name)->
            -    register(Name, self()),
            -    loop().
            +init(Name)->
            +    register(Name, self()),
            +    loop().
             
            -get_config()->
            /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text)
            --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
            +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
            @@ -4,10 +4,10 @@
                      version="3.0">
               
                 common_test - 1.30.0.1
            -    urn:uuid:e3f43c29-7bf5-03d2-caf6-ded05b257f20
            +    urn:uuid:3b592381-9938-21ec-ace4-85a31ce7c453
                 en
             
            -    2026-08-21T03:47:45Z
            +    2042-09-22T17:06:25Z
             
               
               
            /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/cover_chapter.xhtml differs (HTML document, ASCII text, with very long lines (1159))
            --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/cover_chapter.xhtml	2026-08-05 05:56:49.000000000 +0000
            +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/cover_chapter.xhtml	2026-08-05 05:56:49.000000000 +0000
            @@ -63,44 +63,44 @@
             Running Tests and Analyzing Results).

            The Cover Specification File

            General Config

            Here follows the general configuration terms that are allowed in a cover specification file:

            %% List of Nodes on which cover will be active during test.
             %% Nodes = [atom()]
            -{nodes, Nodes}.
            +{nodes, Nodes}.
             
             %% Files with previously exported cover data to include in analysis.
             %% CoverDataFiles = [string()]
            -{import, CoverDataFiles}.
            +{import, CoverDataFiles}.
             
             %% Cover data file to export from this session.
             %% CoverDataFile = string()
            -{export, CoverDataFile}.
            +{export, CoverDataFile}.
             
             %% Cover analysis level.
             %% Level = details | overview
            -{level, Level}.
            +{level, Level}.
             
             %% Directories to include in cover.
             %% Dirs = [string()]
            -{incl_dirs, Dirs}.
            +{incl_dirs, Dirs}.
             
             %% Directories, including subdirectories, to include.
            -{incl_dirs_r, Dirs}.
            +{incl_dirs_r, Dirs}.
             
             %% Specific modules to include in cover.
             %% Mods = [atom()]
            -{incl_mods, Mods}.
            +{incl_mods, Mods}.
             
             %% Directories to exclude in cover.
            -{excl_dirs, Dirs}.
            +{excl_dirs, Dirs}.
             
             %% Directories, including subdirectories, to exclude.
            -{excl_dirs_r, Dirs}.
            +{excl_dirs_r, Dirs}.
             
             %% Specific modules to exclude in cover.
            -{excl_mods, Mods}.
            +{excl_mods, Mods}.
             
             %% Cross cover compilation
             %% Tag = atom(), an identifier for a test run
             %% Mod = [atom()], modules to compile for accumulated analysis
            -{cross,[{Tag,Mods}]}.

            The terms incl_dirs_r and excl_dirs_r tell Common Test to search the +{cross,[{Tag,Mods}]}.

            The terms incl_dirs_r and excl_dirs_r tell Common Test to search the specified directories recursively and include or exclude any module found during the search. The terms incl_dirs and excl_dirs result in a non-recursive search for modules (that is, only modules found in the specified directories are @@ -109,7 +109,7 @@ recompile the modules. It is not sufficient to specify these directories in the cover specification file for Common Test.

            OTP application Config

            When using a cover specification in the testing of an OTP application itself, there is a special incl_app directive that includes the applications modules for -the cover compilation.

            {incl_app, AppName, Cover :: overview | details}.

            Note

            If you desire to also use some other general cover configuration together with +the cover compilation.

            {incl_app, AppName, Cover :: overview | details}.

            Note

            If you desire to also use some other general cover configuration together with this option you should insert the AppName in between the option and its value creating a three tuple.

            Cross Cover Analysis

            The cross cover mechanism allows cover analysis of modules across multiple tests. It is useful if some code, for example, a library module, is used by many @@ -130,7 +130,7 @@ {cross,[{s1,[m1]}]}.

            Then m1 is cover compiled in test run s2, but not shown in the coverage log. Instead, if ct_cover:cross_cover_analyse/2 is called after both s1 and s2 test runs are completed, the accumulated result for m1 is available in the -cross cover log for test run s1.

            The call to the analyze function must be as follows:

            ct_cover:cross_cover_analyse(Level, [{s1,S1LogDir},{s2,S2LogDir}]).

            Here, S1LogDir and S2LogDir are the directories named <TestName>.logs for +cross cover log for test run s1.

            The call to the analyze function must be as follows:

            ct_cover:cross_cover_analyse(Level, [{s1,S1LogDir},{s2,S2LogDir}]).

            Here, S1LogDir and S2LogDir are the directories named <TestName>.logs for each test respectively.

            Notice the tags s1 and s2, which are used in the cover specification file and in the call to ct_cover:cross_cover_analyse/2. The purpose of these is only to map the modules specified in the cover specification to the log /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_ftp.xhtml differs (HTML document, ASCII text, with very long lines (639)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_ftp.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_ftp.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -467,10 +467,10 @@

            Opens an FTP connection and sends a file to the remote host.

            LocalFile and RemoteFile must be absolute paths.

            If the target host is a "special" node, the FTP address must be specified in the -configuration file as follows:

            {node,[{ftp,IpAddr}]}.

            If the target host is something else, for example, a UNIX host, the -configuration file must also include the username and password (both strings):

            {unix,[{ftp,IpAddr},
            -       {username,Username},
            -       {password,Password}]}.

            See also ct:require/2.

            +configuration file as follows:

            {node,[{ftp,IpAddr}]}.

            If the target host is something else, for example, a UNIX host, the +configuration file must also include the username and password (both strings):

            {unix,[{ftp,IpAddr},
            +       {username,Username},
            +       {password,Password}]}.

            See also ct:require/2.

            /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_hooks_chapter.xhtml differs (HTML document, ASCII text, with very long lines (2208)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_hooks_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_hooks_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -91,12 +91,12 @@ always a combination of a result for the suite/group/test and an updated CTHState.

            To let the test suite continue on executing, return the configuration list that you want the test to use as the result.

            All pre hooks, except pre_end_per_testcase/4, can skip or fail the test by -returning a tuple with skip or fail, and a reason as the result.

            Example:

            pre_init_per_suite(SuiteName, Config, CTHState) ->
            -  case db:connect() of
            -    {error,_Reason} ->
            -      {{fail, "Could not connect to DB"}, CTHState};
            -    {ok, Handle} ->
            -      {[{db_handle, Handle} | Config], CTHState#state{ handle = Handle }}
            +returning a tuple with skip or fail, and a reason as the result.

            Example:

            pre_init_per_suite(SuiteName, Config, CTHState) ->
            +  case db:connect() of
            +    {error,_Reason} ->
            +      {{fail, "Could not connect to DB"}, CTHState};
            +    {ok, Handle} ->
            +      {[{db_handle, Handle} | Config], CTHState#state{ handle = Handle }}
               end.

            Note

            If you use multiple CTHs, the first part of the return tuple is used as input for the next CTH. So in the previous example the next CTH can get {fail,Reason} as the second parameter. If you have many CTHs interacting, do @@ -112,18 +112,18 @@ affect the outcome of the test, return the Return data as it is given to the CTH. You can also modify the test result. By returning the Config list with element tc_status removed, you can recover from a test failure. As in all the -pre hooks, it is also possible to fail/skip the test case in the post hook.

            Example:

            post_end_per_testcase(_Suite, _TC, Config, {'EXIT',{_,_}}, CTHState) ->
            -  case db:check_consistency() of
            +pre hooks, it is also possible to fail/skip the test case in the post hook.

            Example:

            post_end_per_testcase(_Suite, _TC, Config, {'EXIT',{_,_}}, CTHState) ->
            +  case db:check_consistency() of
                 true ->
                   %% DB is good, pass the test.
            -      {proplists:delete(tc_status, Config), CTHState};
            +      {proplists:delete(tc_status, Config), CTHState};
                 false ->
                   %% DB is not good, mark as skipped instead of failing
            -      {{skip, "DB is inconsistent!"}, CTHState}
            +      {{skip, "DB is inconsistent!"}, CTHState}
               end;
            -post_end_per_testcase(_Suite, _TC, Config, Return, CTHState) ->
            +post_end_per_testcase(_Suite, _TC, Config, Return, CTHState) ->
               %% Do nothing if tc does not crash.
            -  {Return, CTHState}.

            Note

            Do recover from a testcase failure using CTHs only a last resort. If used + {Return, CTHState}.

            Note

            Do recover from a testcase failure using CTHs only a last resort. If used wrongly, it can be very difficult to determine which tests that pass or fail in a test run.

            Skip and Fail Hooks

            After any post hook has been executed for all installed CTHs, on_tc_fail or @@ -162,80 +162,80 @@ %%% ct_run -suite example_SUITE -pa . -ct_hooks example_cth %%% %%% Note `-pa .`: the hook beam file must be in the code path when installing. --module(example_cth). +-module(example_cth). %% Mandatory Callbacks --export([init/2]). +-export([init/2]). %% Optional Callbacks --export([id/1]). +-export([id/1]). --export([pre_init_per_suite/3]). --export([post_end_per_suite/4]). +-export([pre_init_per_suite/3]). +-export([post_end_per_suite/4]). --export([pre_init_per_testcase/4]). --export([post_end_per_testcase/5]). +-export([pre_init_per_testcase/4]). +-export([post_end_per_testcase/5]). --export([on_tc_skip/4]). +-export([on_tc_skip/4]). --export([terminate/1]). +-export([terminate/1]). %% This hook state is threaded through all the callbacks. --record(state, {filename, total, suite_total, ts, tcs, data, skipped}). +-record(state, {filename, total, suite_total, ts, tcs, data, skipped}). %% This example hook prints its results to a file, see terminate/1. --record(test_run, {total, skipped, suites}). +-record(test_run, {total, skipped, suites}). %% Return a unique id for this CTH. %% Using the filename means the hook can be used with different %% log files to separate timing data within the same test run. %% See Installing a CTH for more information. -id(Opts) -> +id(Opts) -> %% the path is relative to the test run directory - proplists:get_value(filename, Opts, "example_cth.log"). + proplists:get_value(filename, Opts, "example_cth.log"). %% Always called before any other callback function. Use this to initiate %% any common state. -init(Id, _Opts) -> - {ok, #state{filename = Id, total = 0, data = []}}. +init(Id, _Opts) -> + {ok, #state{filename = Id, total = 0, data = []}}. %% Called before init_per_suite is called. -pre_init_per_suite(_Suite,Config,State) -> - {Config, State#state{suite_total = 0, tcs = []}}. +pre_init_per_suite(_Suite,Config,State) -> + {Config, State#state{suite_total = 0, tcs = []}}. %% Called after end_per_suite. -post_end_per_suite(Suite,_Config,Return,State) -> - Data = {suites, Suite, State#state.suite_total, - lists:reverse(State#state.tcs)}, - {Return, State#state{data = [Data | State#state.data], - total = State#state.total + State#state.suite_total}}. +post_end_per_suite(Suite,_Config,Return,State) -> + Data = {suites, Suite, State#state.suite_total, + lists:reverse(State#state.tcs)}, + {Return, State#state{data = [Data | State#state.data], + total = State#state.total + State#state.suite_total}}. %% Called before each init_per_testcase. -pre_init_per_testcase(_Suite,_TC,Config,State) -> - Now = erlang:monotonic_time(microsecond), - {Config, State#state{ts = Now, suite_total = State#state.suite_total + 1}}. +pre_init_per_testcase(_Suite,_TC,Config,State) -> + Now = erlang:monotonic_time(microsecond), + {Config, State#state{ts = Now, suite_total = State#state.suite_total + 1}}. %% Called after each end_per_testcase. -post_end_per_testcase(Suite,TC,_Config,Return,State) -> - Now = erlang:monotonic_time(microsecond), - TCInfo = {testcase, Suite, TC, Return, Now - State#state.ts}, - {Return, State#state{ts = undefined, tcs = [TCInfo | State#state.tcs]}}. +post_end_per_testcase(Suite,TC,_Config,Return,State) -> + Now = erlang:monotonic_time(microsecond), + TCInfo = {testcase, Suite, TC, Return, Now - State#state.ts}, + {Return, State#state{ts = undefined, tcs = [TCInfo | State#state.tcs]}}. %% Called when a test case is skipped by either user action %% or due to an init function failing. -on_tc_skip(_Suite, _TC, _Reason, State) -> - State#state{skipped = State#state.skipped + 1}. +on_tc_skip(_Suite, _TC, _Reason, State) -> + State#state{skipped = State#state.skipped + 1}. %% Called when the scope of the CTH is done. -terminate(State) -> +terminate(State) -> %% use append to avoid data loss if the path is reused - {ok, File} = file:open(State#state.filename, [write, append]), - io:format(File, "~p.~n", [results(State)]), - file:close(File), + {ok, File} = file:open(State#state.filename, [write, append]), + io:format(File, "~p.~n", [results(State)]), + file:close(File), ok. -results(State) -> - #state{skipped = Skipped, data = Data, total = Total} = State, - #test_run{total = Total, skipped = Skipped, suites = lists:reverse(Data)}.

            Built-In CTHs

            Common Test is delivered with some general-purpose CTHs that can be enabled by +results(State) -> + #state{skipped = Skipped, data = Data, total = Total} = State, + #test_run{total = Total, skipped = Skipped, suites = lists:reverse(Data)}.

            Built-In CTHs

            Common Test is delivered with some general-purpose CTHs that can be enabled by the user to provide generic testing functionality. Some of these CTHs are enabled by default when common_test is started to run. They can be disabled by setting enable_builtin_hooks to false on the command line or in the test /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_master_chapter.xhtml differs (HTML document, ASCII text, with very long lines (1303)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_master_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_master_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -36,7 +36,7 @@ of test specifications. If it is a list, the specifications are handled (and the corresponding tests executed) in sequence. An element in a TestSpecs list can also be list of test specifications. The specifications in such a list are -merged into one combined specification before test execution.

            Example:

            ct_master:run(["ts1","ts2",["ts3","ts4"]])

            Here, the tests specified by "ts1" run first, then the tests specified by "ts2", +merged into one combined specification before test execution.

            Example:

            ct_master:run(["ts1","ts2",["ts3","ts4"]])

            Here, the tests specified by "ts1" run first, then the tests specified by "ts2", and finally the tests specified by both "ts3" and "ts4".

            The InclNodes argument to run/3 is a list of node names. Function run/3 runs the tests in TestSpecs just like run/1, but also takes any test in TestSpecs, which is not explicitly tagged with a particular node name, and @@ -70,32 +70,32 @@ install an event handler).

            Consider the example in section Test Specifications in section Running Tests and Analysing Results, now extended with node information and -intended to be executed by Common Test Master:

            {define, 'Top', "/home/test"}.
            -{define, 'T1', "'Top'/t1"}.
            -{define, 'T2', "'Top'/t2"}.
            -{define, 'T3', "'Top'/t3"}.
            -{define, 'CfgFile', "config.cfg"}.
            -{define, 'Node', ct_node}.
            -
            -{node, node1, 'Node@host_x'}.
            -{node, node2, 'Node@host_y'}.
            -
            -{logdir, master, "'Top'/master_logs"}.
            -{logdir, "'Top'/logs"}.
            -
            -{config, node1, "'T1'/'CfgFile'"}.
            -{config, node2, "'T2'/'CfgFile'"}.
            -{config, "'T3'/'CfgFile'"}.
            -
            -{suites, node1, 'T1', all}.
            -{skip_suites, node1, 'T1', [t1B_SUITE,t1D_SUITE], "Not implemented"}.
            -{skip_cases, node1, 'T1', t1A_SUITE, [test3,test4], "Irrelevant"}.
            -{skip_cases, node1, 'T1', t1C_SUITE, [test1], "Ignore"}.
            +intended to be executed by Common Test Master:

            {define, 'Top', "/home/test"}.
            +{define, 'T1', "'Top'/t1"}.
            +{define, 'T2', "'Top'/t2"}.
            +{define, 'T3', "'Top'/t3"}.
            +{define, 'CfgFile', "config.cfg"}.
            +{define, 'Node', ct_node}.
            +
            +{node, node1, 'Node@host_x'}.
            +{node, node2, 'Node@host_y'}.
            +
            +{logdir, master, "'Top'/master_logs"}.
            +{logdir, "'Top'/logs"}.
            +
            +{config, node1, "'T1'/'CfgFile'"}.
            +{config, node2, "'T2'/'CfgFile'"}.
            +{config, "'T3'/'CfgFile'"}.
            +
            +{suites, node1, 'T1', all}.
            +{skip_suites, node1, 'T1', [t1B_SUITE,t1D_SUITE], "Not implemented"}.
            +{skip_cases, node1, 'T1', t1A_SUITE, [test3,test4], "Irrelevant"}.
            +{skip_cases, node1, 'T1', t1C_SUITE, [test1], "Ignore"}.
             
            -{suites, node2, 'T2', [t2B_SUITE,t2C_SUITE]}.
            -{cases, node2, 'T2', t2A_SUITE, [test4,test1,test7]}.
            +{suites, node2, 'T2', [t2B_SUITE,t2C_SUITE]}.
            +{cases, node2, 'T2', t2A_SUITE, [test4,test1,test7]}.
             
            -{skip_suites, 'T3', all, "Not implemented"}.

            This example specifies the same tests as the original example. But now if +{skip_suites, 'T3', all, "Not implemented"}.

            This example specifies the same tests as the original example. But now if started with a call to ct_master:run(TestSpecName), test t1 is executed on node ct_node@host_x (node1), test t2 on ct_node@host_y (node2) and test t3 on both node1 and node2. Configuration file t1 is only read on @@ -112,13 +112,13 @@ Common Test node in question (typically ct@somehost if started with the ct_run program), is performed. Tests without explicit node association are always performed too, of course.

            Automatic Startup of Test Target Nodes

            Initial actions can be started and performed automatically on test target nodes -using test specification term init.

            Two subterms are supported, node_start and eval.

            Example:

            {node, node1, node1@host1}.
            -{node, node2, node1@host2}.
            -{node, node3, node2@host2}.
            -{node, node4, node1@host3}.
            -{init, node1, [{node_start, [{callback_module, my_slave_callback}]}]}.
            -{init, [node2, node3], {node_start, [{username, "ct_user"}, {password, "ct_password"}]}}.
            -{init, node4, {eval, {module, function, []}}}.

            This test specification declares that node1@host1 is to be started using the +using test specification term init.

            Two subterms are supported, node_start and eval.

            Example:

            {node, node1, node1@host1}.
            +{node, node2, node1@host2}.
            +{node, node3, node2@host2}.
            +{node, node4, node1@host3}.
            +{init, node1, [{node_start, [{callback_module, my_slave_callback}]}]}.
            +{init, [node2, node3], {node_start, [{username, "ct_user"}, {password, "ct_password"}]}}.
            +{init, node4, {eval, {module, function, []}}}.

            This test specification declares that node1@host1 is to be started using the user callback function callback_module:my_slave_callback/0, and nodes node1@host2 and node2@host2 are to be started with the default callback module ct_slave. The specified username and password are used to log on to /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_master.xhtml differs (HTML document, ASCII text, with very long lines (804)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_master.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_master.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -326,7 +326,7 @@

            Gets a reference to the Common Test master event manager. The reference can be -used to, for example, add a user-specific event handler while tests are running.

            Example:

            gen_event:add_handler(ct_master:get_event_mgr_ref(), my_ev_h, [])
            +used to, for example, add a user-specific event handler while tests are running.

            Example:

            gen_event:add_handler(ct_master:get_event_mgr_ref(), my_ev_h, [])
            /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_netconfc.xhtml differs (HTML document, ASCII text, with very long lines (1594)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_netconfc.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_netconfc.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -31,7 +31,7 @@ to the server.

            Alternately, open/1,2 can be used to establish a single session on a dedicated connection. (Or, equivalently, only_open/1,2 followed by hello/1-3.)

            Connect/session options can be specified in a configuration file with entries -like the following.

            {server_id(), [option()]}.

            The server_id/0 or an associated ct:target_name/0 can then be passed to +like the following.

            {server_id(), [option()]}.

            The server_id/0 or an associated ct:target_name/0 can then be passed to the aforementioned functions to use the referenced configuration.

            Signaling

            Protocol operations in the NETCONF protocol are realized as remote procedure calls (RPCs) from client to server and a corresponding reply from server to client. RPCs are sent using like-named functions (eg. @@ -44,8 +44,8 @@ in most cases since a non-response by the server or a missing message-id causes the call to hang indefinitely.

            Logging

            The NETCONF server uses error_logger for logging of NETCONF traffic. A special purpose error handler is implemented in ct_conn_log_h. To use this error -handler, add the cth_conn_log hook in the test suite, for example:

            suite() ->
            -    [{ct_hooks, [{cth_conn_log, [{ct:conn_log_mod(), ct:conn_log_options()}]}]}].

            conn_log_mod() is the name of the Common Test module implementing the +handler, add the cth_conn_log hook in the test suite, for example:

            suite() ->
            +    [{ct_hooks, [{cth_conn_log, [{ct:conn_log_mod(), ct:conn_log_options()}]}]}].

            conn_log_mod() is the name of the Common Test module implementing the connection protocol, for example, ct_netconfc.

            Hook option log_type specifies the type of logging:

            • raw - The sent and received NETCONF data is logged to a separate text file "as is" without any formatting. A link to the file is added to the test case HTML log.

            • pretty - The sent and received NETCONF data is logged to a separate text @@ -56,17 +56,17 @@ option hosts and list the names of the servers/connections to be used in the suite. The connections must be named for this to work, that is, they must be opened with open/2.

              Option hosts has no effect if log_type is set to html or silent.

              The hook options can also be specified in a configuration file with -configuration variable ct_conn_log:

              {ct_conn_log,[{ct:conn_log_mod(), ct:conn_log_options()}]}.

              For example:

              {ct_conn_log,[{ct_netconfc,[{log_type,pretty},
              -                            {hosts,[ct:key_or_name()]}]}]}

              Note

              Hook options specified in a configuration file overwrite the hard-coded hook +configuration variable ct_conn_log:

              {ct_conn_log,[{ct:conn_log_mod(), ct:conn_log_options()}]}.

              For example:

              {ct_conn_log,[{ct_netconfc,[{log_type,pretty},
              +                            {hosts,[ct:key_or_name()]}]}]}

              Note

              Hook options specified in a configuration file overwrite the hard-coded hook options in the test suite.

              Logging Example 1:

              The following ct_hooks statement causes pretty printing of NETCONF traffic to separate logs for the connections named nc_server1 and nc_server2. Any other -connections are logged to default NETCONF log.

              suite() ->
              -   [{ct_hooks, [{cth_conn_log, [{ct_netconfc,[{log_type,pretty}},
              -                                              {hosts,[nc_server1,nc_server2]}]}
              -                               ]}]}].

              Connections must be opened as follows:

              open(nc_server1,[...]),
              -open(nc_server2,[...]).

              Logging Example 2:

              The following configuration file causes raw logging of all NETCONF traffic in to -one single text file:

              {ct_conn_log,[{ct_netconfc,[{log_type,raw}]}]}.

              The ct_hooks statement must look as follows:

              suite() ->
              -    [{ct_hooks, [{cth_conn_log, []}]}].

              The same ct_hooks statement without the configuration file would cause HTML +connections are logged to default NETCONF log.

              suite() ->
              +   [{ct_hooks, [{cth_conn_log, [{ct_netconfc,[{log_type,pretty}},
              +                                              {hosts,[nc_server1,nc_server2]}]}
              +                               ]}]}].

              Connections must be opened as follows:

              open(nc_server1,[...]),
              +open(nc_server2,[...]).

              Logging Example 2:

              The following configuration file causes raw logging of all NETCONF traffic in to +one single text file:

              {ct_conn_log,[{ct_netconfc,[{log_type,raw}]}]}.

              The ct_hooks statement must look as follows:

              suite() ->
              +    [{ct_hooks, [{cth_conn_log, []}]}].

              The same ct_hooks statement without the configuration file would cause HTML logging of all NETCONF connections in to the test case HTML log.

              @@ -2051,8 +2051,8 @@

              Edits configuration data.

              By default only the running target is available, unless the server includes :candidate or :startup in its list of capabilities.

              OptParams can be used for specifying optional parameters (default-operation, test-option, or error-option) to be added to the edit-config request. The -value must be a list containing valid simple XML, for example:

              [{'default-operation', ["none"]},
              - {'error-option', ["rollback-on-error"]}]

              If OptParams is not given, the default value [] is used.

              +value must be a list containing valid simple XML, for example:

              [{'default-operation', ["none"]},
              + {'error-option', ["rollback-on-error"]}]

              If OptParams is not given, the default value [] is used.

            /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_property_test_chapter.xhtml differs (HTML document, ASCII text, with very long lines (887)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_property_test_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_property_test_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -21,51 +21,51 @@ property based testing tools in Common Test test suites.

            Basic knowledge of property based testing is assumed in the following. It is also assumed that at least one of the following property based testing tools is installed and available in the library path:

            What Is Supported?

            The ct_property_test module does the following:

            • Compiles the files with property tests in the subdirectory property_test
            • Tests properties in those files using the first found Property Testing Tool.
            • Saves the results - that is the printouts - in the usual Common Test Log

            Introductory Example

            Assume that we want to test the lists:sort/1 function.

            We need a property to test the function. In normal way, we create -property_test/ct_prop.erl module in the test directory in our application:

            -module(ct_prop).
            --export([prop_sort/0]).
            +property_test/ct_prop.erl module in the test directory in our application:

            -module(ct_prop).
            +-export([prop_sort/0]).
             
             %%% This will include the .hrl file for the installed testing tool:
            --include_lib("common_test/include/ct_property_test.hrl").
            +-include_lib("common_test/include/ct_property_test.hrl").
             
             %%% The property we want to check:
             %%%   For all possibly unsorted lists,
             %%%   the result of lists:sort/1 is sorted.
            -prop_sort() ->
            -    ?FORALL(UnSorted, list(),
            -            is_sorted(lists:sort(UnSorted))
            -           ).
            +prop_sort() ->
            +    ?FORALL(UnSorted, list(),
            +            is_sorted(lists:sort(UnSorted))
            +           ).
             
             %%% Function to check that a list is sorted:
            -is_sorted([]) ->
            +is_sorted([]) ->
                 true;
            -is_sorted([_]) ->
            +is_sorted([_]) ->
                 true;
            -is_sorted([H1,H2|SortedTail]) when H1 =< H2 ->
            -    is_sorted([H2|SortedTail]);
            -is_sorted(_) ->
            -    false.

            We also need a CommonTest test suite:

            -module(ct_property_test_SUITE).
            --compile(export_all). % Only in tests!
            +is_sorted([H1,H2|SortedTail]) when H1 =< H2 ->
            +    is_sorted([H2|SortedTail]);
            +is_sorted(_) ->
            +    false.

            We also need a CommonTest test suite:

            -module(ct_property_test_SUITE).
            +-compile(export_all). % Only in tests!
             
            --include_lib("common_test/include/ct.hrl").
            +-include_lib("common_test/include/ct.hrl").
             
            -all() -> [prop_sort
            -         ].
            +all() -> [prop_sort
            +         ].
             
             %%% First prepare Config and compile the property tests for the found tool:
            -init_per_suite(Config) ->
            -    ct_property_test:init_per_suite(Config).
            +init_per_suite(Config) ->
            +    ct_property_test:init_per_suite(Config).
             
            -end_per_suite(Config) ->
            +end_per_suite(Config) ->
                 Config.
             
             %%%================================================================
             %%% Test suites
             %%%
            -prop_sort(Config) ->
            -    ct_property_test:quickcheck(
            -      ct_prop:prop_sort(),
            +prop_sort(Config) ->
            +    ct_property_test:quickcheck(
            +      ct_prop:prop_sort(),
                   Config
            -     ).

            We run it as usual, for example with ct_run in the OS shell:

            ..../test$ ct_run -suite ct_property_test_SUITE
            +     ).

            We run it as usual, for example with ct_run in the OS shell:

            ..../test$ ct_run -suite ct_property_test_SUITE
             .....
             Common Test: Running make in test directories...
             
            @@ -89,13 +89,13 @@
             Testing lib.common_test.ct_property_test_SUITE: TEST COMPLETE, 1 ok, 0 failed of 1 test cases
             
             ....

            A stateful testing example

            Assume a test that generates some parallel stateful commands, and runs 300 -tests:

            prop_parallel(Config) ->
            -    numtests(300,
            -             ?FORALL(Cmds, parallel_commands(?MODULE),
            +tests:

            prop_parallel(Config) ->
            +    numtests(300,
            +             ?FORALL(Cmds, parallel_commands(?MODULE),
                                  begin
            -                         RunResult = run_parallel_commands(?MODULE, Cmds),
            -                         ct_property_test:present_result(?MODULE, Cmds, RunResult, Config)
            -                     end)).

            The ct_property_test:present_result/4 is a help function for printing some + RunResult = run_parallel_commands(?MODULE, Cmds), + ct_property_test:present_result(?MODULE, Cmds, RunResult, Config) + end)).

            The ct_property_test:present_result/4 is a help function for printing some statistics in the CommonTest log file.

            Our example test could for example be a simple test of an ftp server, where we perform get, put and delete requests, some of them in parallel. Per default, the result has three sections:

            *** User 2019-12-11 13:28:17.504 ***
            /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_property_test.xhtml differs (HTML document, ASCII text, with very long lines (850))
            --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_property_test.xhtml	2026-08-05 05:56:49.000000000 +0000
            +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_property_test.xhtml	2026-08-05 05:56:49.000000000 +0000
            @@ -29,30 +29,30 @@
             directory has a subdirectory property_test, where everything needed for the
             property tests are collected. The usual Erlang application directory structure
             is assumed.

            A typical Common Test test suite using ct_property_test is organized as -follows:

            -module(my_prop_test_SUITE).
            --compile(export_all).
            +follows:

            -module(my_prop_test_SUITE).
            +-compile(export_all).
             
            --include_lib("common_test/include/ct.hrl").
            +-include_lib("common_test/include/ct.hrl").
             
            -all() -> [prop_ftp_case].
            +all() -> [prop_ftp_case].
             
            -init_per_suite(Config) ->
            -    ct_property_test:init_per_suite(Config).
            +init_per_suite(Config) ->
            +    ct_property_test:init_per_suite(Config).
             
             %%%---- test case
            -prop_ftp_case(Config) ->
            -    ct_property_test:quickcheck(
            -      ftp_simple_client_server:prop_ftp(),
            +prop_ftp_case(Config) ->
            +    ct_property_test:quickcheck(
            +      ftp_simple_client_server:prop_ftp(),
                   Config
            -     ).

            and the the property test module (in this example + ).

            and the the property test module (in this example ftp_simple_client_server.erl) as almost a usual property testing module (More -examples are in the User's Guide):

            -module(ftp_simple_client_server).
            --export([prop_ftp/0...]).
            +examples are in the User's Guide):

            -module(ftp_simple_client_server).
            +-export([prop_ftp/0...]).
             
            --include_lib("common_test/include/ct_property_test.hrl").
            +-include_lib("common_test/include/ct_property_test.hrl").
             
            -prop_ftp() ->
            -    ?FORALL( ....
            +
            prop_ftp() -> + ?FORALL( ....
            @@ -754,7 +754,7 @@ 'EQC', 'PROPER' or 'TRIQ' set, depending on which tool that is first found. This could make parts of the Erlang property tests code to be included or excluded with the macro directives -ifdef(Macro). or -ifndef(Macro)..

            The file(s) in the property_test subdirectory could, or should, include the -ct_property_test include file:

            -include_lib("common_test/include/ct_property_test.hrl").

            This included file will:

            • Include the correct tool's include file
            • Set the macro 'MOD_eqc' to the correct module name for the selected tool. +ct_property_test include file:

              -include_lib("common_test/include/ct_property_test.hrl").

              This included file will:

              • Include the correct tool's include file
              • Set the macro 'MOD_eqc' to the correct module name for the selected tool. That is, the macro 'MOD_eqc' is set to either eqc, proper or triq.
              @@ -865,8 +865,8 @@

              Presents the result of stateful (statem) property testing using the aggregate function in PropEr, QuickCheck or other similar property testing tool.

              It is assumed to be called inside the property called by quickcheck/2:

              ...
              -RunResult = run_parallel_commands(?MODULE, Cmds),
              -ct_property_test:present_result(?MODULE, Cmds, RunResult, Config)
              +RunResult = run_parallel_commands(?MODULE, Cmds),
              +ct_property_test:present_result(?MODULE, Cmds, RunResult, Config)
               ...

              See the User's Guide for an example of the usage and of the default printout.

              The StatisticsSpec is a list of the tuples:

              • {Title::string(), CollectFun::fun/1}
              • {Title::string(), FrequencyFun::/0, CollectFun::fun/1}

              Each tuple will produce one table in the order of their places in the list.

              • Title will be the title of one result table

              • CollectFun is called with one argument: the Cmds. It should return a list of the values to be counted. The following pre-defined functions exist:

                • ct_property_test:cmnd_names/1 returns a list of commands (function calls) @@ -876,15 +876,15 @@ about sequential and parallel parts from Tool:parallel_commands/1,2
              • FrequencyFun/0 returns a fun/1 which is supposed to take a list of items as input, and return an iolist which will be printed as the table. Per default, the number of each item is counted and the percentage is printed for each. The -list [a,b,a,a,c] could for example return

                ["a 60%\n","b 20%\n","c 20%\n"]

                which will be printed by the print_fun. The default print_fun will print +list [a,b,a,a,c] could for example return

                ["a 60%\n","b 20%\n","c 20%\n"]

                which will be printed by the print_fun. The default print_fun will print it as:

                a 60%
                 b 20%
                -c 20%

              The default StatisticsSpec is:

              • For sequential commands:

                [{"Function calls", fun cmnd_names/1},
                - {"Length of command sequences", fun print_frequency_ranges/0,
                -                                                  fun num_calls/1}]
              • For parallel commands:

                [{"Distribution sequential/parallel", fun sequential_parallel/1},
                - {"Function calls", fun cmnd_names/1},
                - {"Length of command sequences", fun print_frequency_ranges/0,
                -                                                  fun num_calls/1}]
              +c 20%

          The default StatisticsSpec is:

          • For sequential commands:

            [{"Function calls", fun cmnd_names/1},
            + {"Length of command sequences", fun print_frequency_ranges/0,
            +                                                  fun num_calls/1}]
          • For parallel commands:

            [{"Distribution sequential/parallel", fun sequential_parallel/1},
            + {"Function calls", fun cmnd_names/1},
            + {"Length of command sequences", fun print_frequency_ranges/0,
            +                                                  fun num_calls/1}]
          /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_run_cmd.xhtml differs (HTML document, ASCII text, with very long lines (744)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_run_cmd.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_run_cmd.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -113,10 +113,10 @@ [-ct_hooks_order test | config] [-exit_status ignore_config]

        Refresh HTML Index Files

         ct_run -refresh_logs [-logdir LogDir] [-basic_html]
           [-keep_logs all | NLogs]

        Run Common Test in Interactive Mode

         ct_run -shell
        -  [-config ConfigFile1 ConfigFile2 ... ConfigFileN]
        -  [-userconfig CallbackModule1 ConfigString1 and CallbackModule2
        -   ConfigString2 and .. and CallbackModuleN ConfigStringN]
        -  [-decrypt_key Key] | [-decrypt_file KeyFile]

        Start a Common Test Master Node

         ct_run -ctmaster

        See Also

        For information about the start flags, see section + [-config ConfigFile1 ConfigFile2 ... ConfigFileN] + [-userconfig CallbackModule1 ConfigString1 and CallbackModule2 + ConfigString2 and .. and CallbackModuleN ConfigStringN] + [-decrypt_key Key] | [-decrypt_file KeyFile]

        Start a Common Test Master Node

         ct_run -ctmaster

        See Also

        For information about the start flags, see section Running Tests and Analyzing Results in the User's Guide.

        /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_snmp.xhtml differs (HTML document, ASCII text, with very long lines (2283)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_snmp.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_snmp.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -44,15 +44,15 @@ Optional.

      • {agent_target_param_def, [term()] | {data_dir_file, rel_path()}} - Optional.

      Parameter MgrAgentConfName in the functions is to be a name you allocate in your test suite using a require statement. Example (where -MgrAgentConfName = snmp_mgr_agent):

      suite() -> [{require, snmp_mgr_agent, snmp}].

      or

      ct:require(snmp_mgr_agent, snmp).

      Notice that USM users are needed for SNMPv3 configuration and are not to be +MgrAgentConfName = snmp_mgr_agent):

      suite() -> [{require, snmp_mgr_agent, snmp}].

      or

      ct:require(snmp_mgr_agent, snmp).

      Notice that USM users are needed for SNMPv3 configuration and are not to be confused with users.

      SNMP traps, inform, and report messages are handled by the user callback module. For details, see the SNMP application.

      It is recommended to use the .hrl files created by the Erlang/OTP MIB compiler to define the Object Identifiers (OIDs). For example, to get the Erlang node -name from erlNodeTable in the OTP-MIB:

      Oid = ?erlNodeEntry ++ [?erlNodeName, 1]

      Furthermore, values can be set for SNMP application configuration parameters, +name from erlNodeTable in the OTP-MIB:

      Oid = ?erlNodeEntry ++ [?erlNodeName, 1]

      Furthermore, values can be set for SNMP application configuration parameters, config, server, net_if, and so on (for a list of valid parameters and types, see the User's Guide for the SNMP application). -This is done by defining a configuration data variable on the following form:

      {snmp_app, [{manager, [snmp_app_manager_params()]},
      -            {agent, [snmp_app_agent_params()]}]}.

      A name for the data must be allocated in the suite using require (see the +This is done by defining a configuration data variable on the following form:

      {snmp_app, [{manager, [snmp_app_manager_params()]},
      +            {agent, [snmp_app_agent_params()]}]}.

      A name for the data must be allocated in the suite using require (see the example above). Pass this name as argument SnmpAppConfName to ct_snmp:start/3. ct_snmp specifies default values for some SNMP application configuration parameters (such as {verbosity,trace} for /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_ssh.xhtml differs (HTML document, ASCII text, with very long lines (570)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_ssh.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_ssh.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -27,14 +27,14 @@ that have been started on existing SSH connections (that is, when the original connection type is ssh). Whenever the connection type is sftp, use the SSH connection reference only.

      The following options are valid for specifying an SSH/SFTP connection (that is, -can be used as configuration elements):

      [{ConnType, Addr},
      - {port, Port},
      - {user, UserName}
      - {password, Pwd}
      - {user_dir, String}
      - {public_key_alg, PubKeyAlg}
      - {connect_timeout, Timeout}
      - {key_cb, KeyCallbackMod}]

      ConnType = ssh | sftp.

      For other types, see ssh.

      All time-out parameters in ct_ssh functions are values in milliseconds.

      +can be used as configuration elements):

      [{ConnType, Addr},
      + {port, Port},
      + {user, UserName}
      + {password, Pwd}
      + {user_dir, String}
      + {public_key_alg, PubKeyAlg}
      + {connect_timeout, Timeout}
      + {key_cb, KeyCallbackMod}]

      ConnType = ssh | sftp.

      For other types, see ssh.

      All time-out parameters in ct_ssh functions are values in milliseconds.

      /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_telnet.xhtml differs (HTML document, ASCII text, with very long lines (1874)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_telnet.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct_telnet.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -30,14 +30,14 @@ true
    • Polling limit (max number of times to poll to get a remaining string terminated) = 0
    • Polling interval (sleep time between polls) = 1 second
    • The TCP_NODELAY option for the telnet socket is disabled (set to false) per default

    These parameters can be modified by the user with the following configuration -term:

    {telnet_settings, [{connect_timeout,Millisec},
    -                   {command_timeout,Millisec},
    -                   {reconnection_attempts,N},
    -                   {reconnection_interval,Millisec},
    -                   {keep_alive,Bool},
    -                   {poll_limit,N},
    -                   {poll_interval,Millisec},
    -                   {tcp_nodelay,Bool}]}.

    Millisec = timeout(), N = integer()

    Enter the telnet_settings term in a configuration file included in the test +term:

    {telnet_settings, [{connect_timeout,Millisec},
    +                   {command_timeout,Millisec},
    +                   {reconnection_attempts,N},
    +                   {reconnection_interval,Millisec},
    +                   {keep_alive,Bool},
    +                   {poll_limit,N},
    +                   {poll_interval,Millisec},
    +                   {tcp_nodelay,Bool}]}.

    Millisec = timeout(), N = integer()

    Enter the telnet_settings term in a configuration file included in the test and ct_telnet retrieves the information automatically.

    keep_alive can be specified per connection, if necessary. For details, see unix_telnet.

    Logging

    The default logging behavior of ct_telnet is to print information about performed operations, commands, and their corresponding results to the test case @@ -46,8 +46,8 @@ such as expect/3. However, ct_telnet can be configured to use a special purpose event handler, implemented in ct_conn_log_h, for logging all Telnet traffic. To use this handler, install a Common Test hook named -cth_conn_log. Example (using the test suite information function):

    suite() ->
    -    [{ct_hooks, [{cth_conn_log, [{conn_mod(),hook_options()}]}]}].

    conn_mod() is the name of the Common Test module implementing the connection +cth_conn_log. Example (using the test suite information function):

    suite() ->
    +    [{ct_hooks, [{cth_conn_log, [{conn_mod(),hook_options()}]}]}].

    conn_mod() is the name of the Common Test module implementing the connection protocol, that is, ct_telnet.

    The cth_conn_log hook performs unformatted logging of Telnet data to a separate text file. All Telnet communication is captured and printed, including any data sent from the server. The link to this text file is located at the top @@ -64,15 +64,15 @@ disabled, which results with no prefix data. If the value is set to full prefix contains timestamp and additonal information. If the value is set to short prefix includes only human readable timestamp.

    All cth_conn_log hook options described can also be specified in a -configuration file with configuration variable ct_conn_log.

    Example:

    {ct_conn_log, [{ct_telnet,[{log_type,raw},
    -                           {hosts,[key_or_name()]}]}]}

    Note

    Hook options specified in a configuration file overwrite any hard-coded hook +configuration file with configuration variable ct_conn_log.

    Example:

    {ct_conn_log, [{ct_telnet,[{log_type,raw},
    +                           {hosts,[key_or_name()]}]}]}

    Note

    Hook options specified in a configuration file overwrite any hard-coded hook options in the test suite.

    Logging Example:

    The following ct_hooks statement causes printing of Telnet traffic to separate logs for the connections server1 and server2. Traffic for any other -connections is logged in the default Telnet log.

    suite() ->
    -    [{ct_hooks,
    -      [{cth_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}]}].

    As previously explained, this specification can also be provided by an entry -like the following in a configuration file:

    {ct_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}.

    In this case the ct_hooks statement in the test suite can look as follows:

    suite() ->
    -    [{ct_hooks, [{cth_conn_log, []}]}].

    See Also

    unix_telnet

    +connections is logged in the default Telnet log.

    suite() ->
    +    [{ct_hooks,
    +      [{cth_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}]}].

    As previously explained, this specification can also be provided by an entry +like the following in a configuration file:

    {ct_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}.

    In this case the ct_hooks statement in the test suite can look as follows:

    suite() ->
    +    [{ct_hooks, [{cth_conn_log, []}]}].

    See Also

    unix_telnet

    @@ -759,9 +759,9 @@ instead of only one Match. Also HaltReason is returned.

  • sequence - All patterns must be matched in a sequence. A match is not concluded until all patterns are matched. This option can be interrupted by one or more HaltPatterns. MatchList is always returned, that is, a list of -Match instead of only one Match. Also HaltReason is returned.

  • Example 1:

    expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],[sequence,{halt,[{nnn,"NNN"}]}])

    First this tries to match "ABC", and then "XYZ", but if "NNN" appears, the +Match instead of only one Match. Also HaltReason is returned.

    Example 1:

    expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],[sequence,{halt,[{nnn,"NNN"}]}])

    First this tries to match "ABC", and then "XYZ", but if "NNN" appears, the function returns {error,{nnn,["NNN"]}}. If both "ABC" and "XYZ" are -matched, the function returns {ok,[AbcMatch,XyzMatch]}.

    Example 2:

    expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],[{repeat,2},{halt,[{nnn,"NNN"}]}])

    This tries to match "ABC" or "XYZ" twice. If "NNN" appears, the function +matched, the function returns {ok,[AbcMatch,XyzMatch]}.

    Example 2:

    expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],[{repeat,2},{halt,[{nnn,"NNN"}]}])

    This tries to match "ABC" or "XYZ" twice. If "NNN" appears, the function returns HaltReason = {nnn,["NNN"]}.

    Options repeat and sequence can be combined to match a sequence multiple times.

    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct.xhtml differs (HTML document, ASCII text, with very long lines (384)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/ct.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -1862,17 +1862,17 @@

    Reads configuration data values.

    Returns the matching values or configuration elements, given a configuration variable key or its associated name (if one has been specified with -ct:require/2 or a require statement).

    Example:

    Given the following configuration file:

    {unix,[{telnet,IpAddr},
    -       {user,[{username,Username},
    -              {password,Password}]}]}.

    Then:

    ct:get_config(unix,Default) -> [{telnet,IpAddr},
    - {user, [{username,Username}, {password,Password}]}]
    -ct:get_config({unix,telnet},Default) -> IpAddr
    -ct:get_config({unix,user,username},Default) -> Username
    -ct:get_config({unix,ftp},Default) -> Default
    -ct:get_config(unknownkey,Default) -> Default

    If a configuration variable key has been associated with a name (by +ct:require/2 or a require statement).

    Example:

    Given the following configuration file:

    {unix,[{telnet,IpAddr},
    +       {user,[{username,Username},
    +              {password,Password}]}]}.

    Then:

    ct:get_config(unix,Default) -> [{telnet,IpAddr},
    + {user, [{username,Username}, {password,Password}]}]
    +ct:get_config({unix,telnet},Default) -> IpAddr
    +ct:get_config({unix,user,username},Default) -> Username
    +ct:get_config({unix,ftp},Default) -> Default
    +ct:get_config(unknownkey,Default) -> Default

    If a configuration variable key has been associated with a name (by ct:require/2 or a require statement), the name can be used -instead of the key to read the value:

    ct:require(myuser,{unix,user}) -> ok.
    -ct:get_config(myuser,Default) -> [{username,Username}, {password,Password}]

    If a configuration variable is defined in multiple files, use option all to +instead of the key to read the value:

    ct:require(myuser,{unix,user}) -> ok.
    +ct:get_config(myuser,Default) -> [{username,Username}, {password,Password}]

    If a configuration variable is defined in multiple files, use option all to access all possible values. The values are returned in a list. The order of the elements corresponds to the order that the configuration files were specified at startup.

    If configuration elements (key-value tuples) are to be returned as result @@ -1910,7 +1910,7 @@

    Gets a reference to the Common Test event manager. The reference can be used -to, for example, add a user-specific event handler while tests are running.

    Example:

    gen_event:add_handler(ct:get_event_mgr_ref(), my_ev_h, [])
    +to, for example, add a user-specific event handler while tests are running.

    Example:

    gen_event:add_handler(ct:get_event_mgr_ref(), my_ev_h, [])
    @@ -2198,7 +2198,7 @@ -

    Installs configuration files and event handlers.

    Run this function once before the first test.

    Example:

    install([{config,["config_node.ctc","config_user.ctc"]}])

    This function is automatically run by program ct_run.

    +

    Installs configuration files and event handlers.

    Run this function once before the first test.

    Example:

    install([{config,["config_node.ctc","config_user.ctc"]}])

    This function is automatically run by program ct_run.

    @@ -3035,7 +3035,7 @@

    Checks if the required configuration is available. Arbitrarily deep tuples can be specified as Required. Only the last element of the tuple can be a list of -SubKeys.

    Example 1. Require the variable myvar:

    ok = ct:require(myvar).

    In this case the configuration file must at least contain:

    {myvar,Value}.

    Example 2. Require key myvar with subkeys sub1 and sub2:

    ok = ct:require({myvar,[sub1,sub2]}).

    In this case the configuration file must at least contain:

    {myvar,[{sub1,Value},{sub2,Value}]}.

    Example 3. Require key myvar with subkey sub1 with subsub1:

    ok = ct:require({myvar,sub1,sub2}).

    In this case the configuration file must at least contain:

    {myvar,[{sub1,[{sub2,Value}]}]}.

    See also ct:get_config/1, +SubKeys.

    Example 1. Require the variable myvar:

    ok = ct:require(myvar).

    In this case the configuration file must at least contain:

    {myvar,Value}.

    Example 2. Require key myvar with subkeys sub1 and sub2:

    ok = ct:require({myvar,[sub1,sub2]}).

    In this case the configuration file must at least contain:

    {myvar,[{sub1,Value},{sub2,Value}]}.

    Example 3. Require key myvar with subkey sub1 with subsub1:

    ok = ct:require({myvar,sub1,sub2}).

    In this case the configuration file must at least contain:

    {myvar,[{sub1,[{sub2,Value}]}]}.

    See also ct:get_config/1, ct:get_config/2, ct:get_config/3, ct:require/2.

    @@ -3077,8 +3077,8 @@ that the value of the element can be read with ct:get_config/1,2 provided Name is used instead of the whole Required term.

    Example:

    Require one node with a Telnet connection and an FTP connection. Name the node -a:

    ok = ct:require(a,{machine,node}).

    All references to this node can then use the node name. For example, a file over -FTP is fetched like follows:

    ok = ct:ftp_get(a,RemoteFile,LocalFile).

    For this to work, the configuration file must at least contain:

    {machine,[{node,[{telnet,IpAddr},{ftp,IpAddr}]}]}.

    Note

    The behavior of this function changed radically in Common Test 1.6.2. To +a:

    ok = ct:require(a,{machine,node}).

    All references to this node can then use the node name. For example, a file over +FTP is fetched like follows:

    ok = ct:ftp_get(a,RemoteFile,LocalFile).

    For this to work, the configuration file must at least contain:

    {machine,[{node,[{telnet,IpAddr},{ftp,IpAddr}]}]}.

    Note

    The behavior of this function changed radically in Common Test 1.6.2. To keep some backwards compatibility, it is still possible to do: ct:require(a,{node,[telnet,ftp]}). This associates the name a with the top-level node entry. For this to work, the configuration file must at least @@ -3453,12 +3453,12 @@ the Erlang shell. The interactive mode can also be started from the OS command line with ct_run -shell [-config File...].

    If any functions (for example, Telnet or FTP) using "required configuration data" are to be called from the Erlang shell, configuration data must first be -required with ct:require/2.

    Example:

    > ct:require(unix_telnet, unix).
    +required with ct:require/2.

    Example:

    > ct:require(unix_telnet, unix).
     ok
    -> ct_telnet:open(unix_telnet).
    -{ok,<0.105.0>}
    -> ct_telnet:cmd(unix_telnet, "ls .").
    -{ok,["ls","file1  ...",...]}
    +>
    ct_telnet:open(unix_telnet). +{ok,<0.105.0>} +> ct_telnet:cmd(unix_telnet, "ls ."). +{ok,["ls","file1 ...",...]}
    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/dependencies_chapter.xhtml differs (HTML document, ASCII text, with very long lines (1170)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/dependencies_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/dependencies_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -47,65 +47,65 @@ start and stop functionality separately.) The configuration can also be implemented as a common function, maybe grouped with the start function. Finally, the testing of connecting and disconnecting a client can be grouped -into one test case. The resulting suite can look as follows:

    -module(my_server_SUITE).
    --compile(export_all).
    --include_lib("ct.hrl").
    +into one test case. The resulting suite can look as follows:

    -module(my_server_SUITE).
    +-compile(export_all).
    +-include_lib("ct.hrl").
     
     %%% init and end functions...
     
    -suite() -> [{require,my_server_cfg}].
    +suite() -> [{require,my_server_cfg}].
     
    -init_per_testcase(start_and_stop, Config) ->
    +init_per_testcase(start_and_stop, Config) ->
         Config;
     
    -init_per_testcase(config, Config) ->
    -    [{server_pid,start_server()} | Config];
    +init_per_testcase(config, Config) ->
    +    [{server_pid,start_server()} | Config];
     
    -init_per_testcase(_, Config) ->
    -    ServerPid = start_server(),
    -    configure_server(),
    -    [{server_pid,ServerPid} | Config].
    +init_per_testcase(_, Config) ->
    +    ServerPid = start_server(),
    +    configure_server(),
    +    [{server_pid,ServerPid} | Config].
     
    -end_per_testcase(start_and_stop, _) ->
    +end_per_testcase(start_and_stop, _) ->
         ok;
     
    -end_per_testcase(_, Config) ->
    -    ServerPid = proplists:get_value(server_pid, Config),
    -    stop_server(ServerPid).
    +end_per_testcase(_, Config) ->
    +    ServerPid = proplists:get_value(server_pid, Config),
    +    stop_server(ServerPid).
     
     %%% test cases...
     
    -all() -> [start_and_stop, config, connect_and_disconnect].
    +all() -> [start_and_stop, config, connect_and_disconnect].
     
     %% test that starting and stopping works
    -start_and_stop(_) ->
    -    ServerPid = start_server(),
    -    stop_server(ServerPid).
    +start_and_stop(_) ->
    +    ServerPid = start_server(),
    +    stop_server(ServerPid).
     
     %% configuration test
    -config(Config) ->
    -    ServerPid = proplists:get_value(server_pid, Config),
    -    configure_server(ServerPid).
    +config(Config) ->
    +    ServerPid = proplists:get_value(server_pid, Config),
    +    configure_server(ServerPid).
     
     %% test connecting and disconnecting client
    -connect_and_disconnect(Config) ->
    -    ServerPid = proplists:get_value(server_pid, Config),
    -    {ok,SessionId} = my_server:connect(ServerPid),
    -    ok = my_server:disconnect(ServerPid, SessionId).
    +connect_and_disconnect(Config) ->
    +    ServerPid = proplists:get_value(server_pid, Config),
    +    {ok,SessionId} = my_server:connect(ServerPid),
    +    ok = my_server:disconnect(ServerPid, SessionId).
     
     %%% common functions...
     
    -start_server() ->
    -    {ok,ServerPid} = my_server:start(),
    +start_server() ->
    +    {ok,ServerPid} = my_server:start(),
         ServerPid.
     
    -stop_server(ServerPid) ->
    -    ok = my_server:stop(),
    +stop_server(ServerPid) ->
    +    ok = my_server:stop(),
         ok.
     
    -configure_server(ServerPid) ->
    -    ServerCfgData = ct:get_config(my_server_cfg),
    -    ok = my_server:configure(ServerPid, ServerCfgData),
    +configure_server(ServerPid) ->
    +    ServerCfgData = ct:get_config(my_server_cfg),
    +    ok = my_server:configure(ServerPid, ServerCfgData),
         ok.

    Saving Configuration Data

    Sometimes it is impossible, or infeasible, to implement independent test cases. Maybe it is not possible to read the SUT state. Maybe resetting the SUT is impossible and it takes too long time to restart the system. In situations where @@ -127,40 +127,40 @@ data is to be saved by finction end_per_suite and read by function init_per_suite in the suite that follows. When passing data between suites, Saver carries the name -of the test suite.

    Example:

    -module(server_b_SUITE).
    --compile(export_all).
    --include_lib("ct.hrl").
    +of the test suite.

    Example:

    -module(server_b_SUITE).
    +-compile(export_all).
    +-include_lib("ct.hrl").
     
     %%% init and end functions...
     
    -init_per_suite(Config) ->
    +init_per_suite(Config) ->
         %% read config saved by previous test suite
    -    {server_a_SUITE,OldConfig} = proplists:get_value(saved_config, Config),
    +    {server_a_SUITE,OldConfig} = proplists:get_value(saved_config, Config),
         %% extract server identity (comes from server_a_SUITE)
    -    ServerId = proplists:get_value(server_id, OldConfig),
    -    SessionId = connect_to_server(ServerId),
    -    [{ids,{ServerId,SessionId}} | Config].
    +    ServerId = proplists:get_value(server_id, OldConfig),
    +    SessionId = connect_to_server(ServerId),
    +    [{ids,{ServerId,SessionId}} | Config].
     
    -end_per_suite(Config) ->
    +end_per_suite(Config) ->
         %% save config for server_c_SUITE (session_id and server_id)
    -    {save_config,Config}
    +    {save_config,Config}
     
     %%% test cases...
     
    -all() -> [allocate, deallocate].
    +all() -> [allocate, deallocate].
     
    -allocate(Config) ->
    -    {ServerId,SessionId} = proplists:get_value(ids, Config),
    -    {ok,Handle} = allocate_resource(ServerId, SessionId),
    +allocate(Config) ->
    +    {ServerId,SessionId} = proplists:get_value(ids, Config),
    +    {ok,Handle} = allocate_resource(ServerId, SessionId),
         %% save handle for deallocation test
    -    NewConfig = [{handle,Handle}],
    -    {save_config,NewConfig}.
    +    NewConfig = [{handle,Handle}],
    +    {save_config,NewConfig}.
     
    -deallocate(Config) ->
    -    {ServerId,SessionId} = proplists:get_value(ids, Config),
    -    {allocate,OldConfig} = proplists:get_value(saved_config, Config),
    -    Handle = proplists:get_value(handle, OldConfig),
    -    ok = deallocate_resource(ServerId, SessionId, Handle).

    To save Config data from a test case that is to be skipped, return tuple +deallocate(Config) -> + {ServerId,SessionId} = proplists:get_value(ids, Config), + {allocate,OldConfig} = proplists:get_value(saved_config, Config), + Handle = proplists:get_value(handle, OldConfig), + ok = deallocate_resource(ServerId, SessionId, Handle).

    To save Config data from a test case that is to be skipped, return tuple {skip_and_save,Reason,ConfigList}.

    The result is that the test case is skipped with Reason printed to the log file (as described earlier) and ConfigList is saved for the next test case. ConfigList can be read using proplists:get_value(saved_config, Config), as @@ -174,22 +174,22 @@ property. Test case groups are defined through function groups/0 in the test suite (for details, see section Test Case Groups.

    For example, to ensure that if allocate in server_b_SUITE crashes, -deallocate is skipped, the following sequence can be defined:

    groups() -> [{alloc_and_dealloc, [sequence], [alloc,dealloc]}].

    Assume that the suite contains the test case get_resource_status that is -independent of the other two cases, then function all can look as follows:

    all() -> [{group,alloc_and_dealloc}, get_resource_status].

    If alloc succeeds, dealloc is also executed. If alloc fails however, +deallocate is skipped, the following sequence can be defined:

    groups() -> [{alloc_and_dealloc, [sequence], [alloc,dealloc]}].

    Assume that the suite contains the test case get_resource_status that is +independent of the other two cases, then function all can look as follows:

    all() -> [{group,alloc_and_dealloc}, get_resource_status].

    If alloc succeeds, dealloc is also executed. If alloc fails however, dealloc is not executed but marked as SKIPPED in the HTML log. get_resource_status runs no matter what happens to the alloc_and_dealloc cases.

    Test cases in a sequence are executed in order until all succeed or one fails. If one fails, all following cases in the sequence are skipped. The cases in the sequence that have succeeded up to that point are reported as successful in the -log. Any number of sequences can be specified.

    Example:

    groups() -> [{scenarioA, [sequence], [testA1, testA2]},
    -             {scenarioB, [sequence], [testB1, testB2, testB3]}].
    +log. Any number of sequences can be specified.

    Example:

    groups() -> [{scenarioA, [sequence], [testA1, testA2]},
    +             {scenarioB, [sequence], [testB1, testB2, testB3]}].
     
    -all() -> [test1,
    +all() -> [test1,
               test2,
    -          {group,scenarioA},
    +          {group,scenarioA},
               test3,
    -          {group,scenarioB},
    -          test4].

    A sequence group can have subgroups. Such subgroups can have any property, that + {group,scenarioB}, + test4].

    A sequence group can have subgroups. Such subgroups can have any property, that is, they are not required to also be sequences. If you want the status of the subgroup to affect the sequence on the level above, return {return_group_result,Status} from /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/event_handler_chapter.xhtml differs (HTML document, ASCII text, with very long lines (1529)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/event_handler_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/event_handler_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -48,12 +48,12 @@ ct_run -event_handler_init instead of -event_handler.

    Note

    All event handler modules must have gen_event behavior. These modules must be precompiled and their locations must be added explicitly to the Erlang code server search path (as in the previous example).

    An event_handler tuple in argument Opts has the following definition (see -ct:run_test/1):

    {event_handler,EventHandlers}
    +ct:run_test/1):

    {event_handler,EventHandlers}
     
    -EventHandlers = EH | [EH]
    -EH = atom() | {atom(),InitArgs} | {[atom()],InitArgs}
    -InitArgs = [term()]

    In the following example, two event handlers for the my_SUITE test are -installed:

    1> ct:run_test([{suite,"test/my_SUITE"},{event_handler,[my_evh1,{my_evh2,[node()]}]}]).

    Event handler my_evh1 is started with [] as argument to the init function. +EventHandlers = EH | [EH] +EH = atom() | {atom(),InitArgs} | {[atom()],InitArgs} +InitArgs = [term()]

    In the following example, two event handlers for the my_SUITE test are +installed:

    1> ct:run_test([{suite,"test/my_SUITE"},{event_handler,[my_evh1,{my_evh2,[node()]}]}]).

    Event handler my_evh1 is started with [] as argument to the init function. Event handler my_evh2 is started with the name of the current node in the init argument list.

    Event handlers can also be plugged in using one of the following test specification terms:

    • {event_handler, EventHandlers}
    • {event_handler, EventHandlers, InitArgs}
    • {event_handler, NodeRefs, EventHandlers}
    • {event_handler, NodeRefs, EventHandlers, InitArgs}

    EventHandlers is a list of module names. Before a test session starts, the /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/example_chapter.xhtml differs (HTML document, ASCII text, with very long lines (734)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/example_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/example_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -17,19 +17,19 @@

    Examples and Templates

    -

    Test Suite Example

    The following example test suite shows some tests of a database server:

    -module(db_data_type_SUITE).
    +

    Test Suite Example

    The following example test suite shows some tests of a database server:

    -module(db_data_type_SUITE).
     
    --include_lib("common_test/include/ct.hrl").
    +-include_lib("common_test/include/ct.hrl").
     
     %% Test server callbacks
    --export([suite/0, all/0,
    +-export([suite/0, all/0,
              init_per_suite/1, end_per_suite/1,
    -         init_per_testcase/2, end_per_testcase/2]).
    +         init_per_testcase/2, end_per_testcase/2]).
     
     %% Test cases
    --export([string/1, integer/1]).
    +-export([string/1, integer/1]).
     
    --define(CONNECT_STR, "DSN=sqlserver;UID=alladin;PWD=sesame").
    +-define(CONNECT_STR, "DSN=sqlserver;UID=alladin;PWD=sesame").
     
     %%--------------------------------------------------------------------
     %% COMMON TEST CALLBACK FUNCTIONS
    @@ -44,8 +44,8 @@
     %% Description: Returns list of tuples to set default properties
     %%              for the suite.
     %%--------------------------------------------------------------------
    -suite() ->
    -    [{timetrap,{minutes,1}}].
    +suite() ->
    +    [{timetrap,{minutes,1}}].
     
     %%--------------------------------------------------------------------
     %% Function: init_per_suite(Config0) -> Config1
    @@ -55,10 +55,10 @@
     %%
     %% Description: Initialization before the suite.
     %%--------------------------------------------------------------------
    -init_per_suite(Config) ->
    -    {ok, Ref} = db:connect(?CONNECT_STR, []),
    -    TableName = db_lib:unique_table_name(),
    -    [{con_ref, Ref },{table_name, TableName}| Config].
    +init_per_suite(Config) ->
    +    {ok, Ref} = db:connect(?CONNECT_STR, []),
    +    TableName = db_lib:unique_table_name(),
    +    [{con_ref, Ref },{table_name, TableName}| Config].
     
     %%--------------------------------------------------------------------
     %% Function: end_per_suite(Config) -> term()
    @@ -68,9 +68,9 @@
     %%
     %% Description: Cleanup after the suite.
     %%--------------------------------------------------------------------
    -end_per_suite(Config) ->
    -    Ref = proplists:get_value(con_ref, Config),
    -    db:disconnect(Ref),
    +end_per_suite(Config) ->
    +    Ref = proplists:get_value(con_ref, Config),
    +    db:disconnect(Ref),
         ok.
     
     %%--------------------------------------------------------------------
    @@ -83,10 +83,10 @@
     %%
     %% Description: Initialization before each test case.
     %%--------------------------------------------------------------------
    -init_per_testcase(Case, Config) ->
    -    Ref = proplists:get_value(con_ref, Config),
    -    TableName = proplists:get_value(table_name, Config),
    -    ok = db:create_table(Ref, TableName, table_type(Case)),
    +init_per_testcase(Case, Config) ->
    +    Ref = proplists:get_value(con_ref, Config),
    +    TableName = proplists:get_value(table_name, Config),
    +    ok = db:create_table(Ref, TableName, table_type(Case)),
         Config.
     
     %%--------------------------------------------------------------------
    @@ -99,10 +99,10 @@
     %%
     %% Description: Cleanup after each test case.
     %%--------------------------------------------------------------------
    -end_per_testcase(_Case, Config) ->
    -    Ref = proplists:get_value(con_ref, Config),
    -    TableName = proplists:get_value(table_name, Config),
    -    ok = db:delete_table(Ref, TableName),
    +end_per_testcase(_Case, Config) ->
    +    Ref = proplists:get_value(con_ref, Config),
    +    TableName = proplists:get_value(table_name, Config),
    +    ok = db:delete_table(Ref, TableName),
         ok.
     
     %%--------------------------------------------------------------------
    @@ -117,28 +117,28 @@
     %% Description: Returns the list of groups and test cases that
     %%              are to be executed.
     %%--------------------------------------------------------------------
    -all() ->
    -    [string, integer].
    +all() ->
    +    [string, integer].
     
     
     %%--------------------------------------------------------------------
     %% TEST CASES
     %%--------------------------------------------------------------------
     
    -string(Config) ->
    -    insert_and_lookup(dummy_key, "Dummy string", Config).
    +string(Config) ->
    +    insert_and_lookup(dummy_key, "Dummy string", Config).
     
    -integer(Config) ->
    -    insert_and_lookup(dummy_key, 42, Config).
    +integer(Config) ->
    +    insert_and_lookup(dummy_key, 42, Config).
     
     
    -insert_and_lookup(Key, Value, Config) ->
    -    Ref = proplists:get_value(con_ref, Config),
    -    TableName = proplists:get_value(table_name, Config),
    -    ok = db:insert(Ref, TableName, Key, Value),
    -    [Value] = db:lookup(Ref, TableName, Key),
    -    ok = db:delete(Ref, TableName, Key),
    -    [] = db:lookup(Ref, TableName, Key),
    +insert_and_lookup(Key, Value, Config) ->
    +    Ref = proplists:get_value(con_ref, Config),
    +    TableName = proplists:get_value(table_name, Config),
    +    ok = db:insert(Ref, TableName, Key, Value),
    +    [Value] = db:lookup(Ref, TableName, Key),
    +    ok = db:delete(Ref, TableName, Key),
    +    [] = db:lookup(Ref, TableName, Key),
         ok.

    Test Suite Templates

    The Erlang mode for the Emacs editor includes two Common Test test suite templates, one with extensive information in the function headers, and one with minimal information. A test suite template provides a quick start for @@ -150,12 +150,12 @@ %%% %%% Created : %%%------------------------------------------------------------------- --module(example_SUITE). +-module(example_SUITE). %% Note: This directive should only be used in test suites. --compile(export_all). +-compile(export_all). --include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/include/ct.hrl"). %%-------------------------------------------------------------------- %% COMMON TEST CALLBACK FUNCTIONS @@ -173,8 +173,8 @@ %% Note: The suite/0 function is only meant to be used to return %% default data values, not perform any other operations. %%-------------------------------------------------------------------- -suite() -> - [{timetrap,{minutes,10}}]. +suite() -> + [{timetrap,{minutes,10}}]. %%-------------------------------------------------------------------- %% Function: init_per_suite(Config0) -> @@ -190,7 +190,7 @@ %% 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) -> +init_per_suite(Config) -> Config. %%-------------------------------------------------------------------- @@ -201,7 +201,7 @@ %% %% Description: Cleanup after the suite. %%-------------------------------------------------------------------- -end_per_suite(_Config) -> +end_per_suite(_Config) -> ok. %%-------------------------------------------------------------------- @@ -217,7 +217,7 @@ %% %% Description: Initialization before each test case group. %%-------------------------------------------------------------------- -init_per_group(_GroupName, Config) -> +init_per_group(_GroupName, Config) -> Config. %%-------------------------------------------------------------------- @@ -231,7 +231,7 @@ %% %% Description: Cleanup after each test case group. %%-------------------------------------------------------------------- -end_per_group(_GroupName, _Config) -> +end_per_group(_GroupName, _Config) -> ok. /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/getting_started_chapter.xhtml differs (HTML document, ASCII text, with very long lines (1623)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/getting_started_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/getting_started_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -43,47 +43,47 @@ the test suite module implements callback functions (mandatory or optional) for various purposes, for example:

    • Init/end configuration function for the test suite
    • Init/end configuration function for a test case
    • Init/end configuration function for a test case group
    • Test cases

    The configuration functions are optional. The following example is a test suite without configuration functions, including one simple test case, to check that -module mymod exists (that is, can be successfully loaded by the code server):

    -module(my1st_SUITE).
    --compile(export_all).
    +module mymod exists (that is, can be successfully loaded by the code server):

    -module(my1st_SUITE).
    +-compile(export_all).
     
    -all() ->
    -    [mod_exists].
    +all() ->
    +    [mod_exists].
     
    -mod_exists(_) ->
    -    {module,mymod} = code:load_file(mymod).

    If the operation fails, a bad match error occurs that terminates the test case.

    A Test Suite with Configuration Functions

    If you need to perform configuration operations to run your test, you can +mod_exists(_) -> + {module,mymod} = code:load_file(mymod).

    If the operation fails, a bad match error occurs that terminates the test case.

    A Test Suite with Configuration Functions

    If you need to perform configuration operations to run your test, you can implement configuration functions in your suite. The result from a configuration function is configuration data, or Config. This is a list of key-value tuples that get passed from the configuration function to the test cases (possibly through configuration functions on "lower level"). The data flow looks as follows:

    Configuration Data Flow in a Suite

    The following example shows a test suite that uses configuration functions to open and close a log file for the test cases (an operation that is unnecessary -and irrelevant to perform by each test case):

    -module(check_log_SUITE).
    --export([all/0, init_per_suite/1, end_per_suite/1]).
    --export([check_restart_result/1, check_no_errors/1]).
    +and irrelevant to perform by each test case):

    -module(check_log_SUITE).
    +-export([all/0, init_per_suite/1, end_per_suite/1]).
    +-export([check_restart_result/1, check_no_errors/1]).
     
    --define(value(Key,Config), proplists:get_value(Key,Config)).
    +-define(value(Key,Config), proplists:get_value(Key,Config)).
     
    -all() -> [check_restart_result, check_no_errors].
    +all() -> [check_restart_result, check_no_errors].
     
    -init_per_suite(InitConfigData) ->
    -    [{logref,open_log()} | InitConfigData].
    +init_per_suite(InitConfigData) ->
    +    [{logref,open_log()} | InitConfigData].
     
    -end_per_suite(ConfigData) ->
    -    close_log(?value(logref, ConfigData)).
    +end_per_suite(ConfigData) ->
    +    close_log(?value(logref, ConfigData)).
     
    -check_restart_result(ConfigData) ->
    -    TestData = read_log(restart, ?value(logref, ConfigData)),
    -    {match,_Line} = search_for("restart successful", TestData).
    +check_restart_result(ConfigData) ->
    +    TestData = read_log(restart, ?value(logref, ConfigData)),
    +    {match,_Line} = search_for("restart successful", TestData).
     
    -check_no_errors(ConfigData) ->
    -    TestData = read_log(all, ?value(logref, ConfigData)),
    -    case search_for("error", TestData) of
    -        {match,Line} -> ct:fail({error_found_in_log,Line});
    +check_no_errors(ConfigData) ->
    +    TestData = read_log(all, ?value(logref, ConfigData)),
    +    case search_for("error", TestData) of
    +        {match,Line} -> ct:fail({error_found_in_log,Line});
             nomatch -> ok
         end.

    The test cases verify, by parsing a log file, that our SUT has performed a successful restart and that no unexpected errors are printed.

    To execute the test cases in the recent test suite, type the following on the UNIX/Linux command line (assuming that the suite module is in the current -working directory):

    $ ct_run -dir .

    or:

    $ ct_run -suite check_log_SUITE

    To use the Erlang shell to run our test, you can evaluate the following call:

    1> ct:run_test([{dir, "."}]).

    or:

    1> ct:run_test([{suite, "check_log_SUITE"}]).

    The result from running the test is printed in log files in HTML format (stored +working directory):

    $ ct_run -dir .

    or:

    $ ct_run -suite check_log_SUITE

    To use the Erlang shell to run our test, you can evaluate the following call:

    1> ct:run_test([{dir, "."}]).

    or:

    1> ct:run_test([{suite, "check_log_SUITE"}]).

    The result from running the test is printed in log files in HTML format (stored in unique log directories on a different level). The following illustration shows the log file structure:

    HTML Log File Structure

    Questions and Answers

    Here follows some questions that you might have after reading this section with corresponding tips and links to the answers:

    • Question: "How and where can I specify variable data for my tests that must /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/run_test_chapter.xhtml differs (HTML document, ASCII text, with very long lines (3302)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/run_test_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/run_test_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -136,7 +136,7 @@ which instead is printed to tty at the end of the test run.

      Note

      To use the functions ct:break/1,2 and ct:continue/0,1, release_shell must be set to true.

      For details, see ct:run_test/1 manual page.

      Test Case Group Execution

      With the ct_run flag, or ct:run_test/1 option group, one or more test case groups can be specified, optionally in combination with specific test cases. The -syntax for specifying groups on the command line is as follows:

      $ ct_run -group <group_names_or_paths> [-case <cases>]

      The syntax in the Erlang shell is as follows:

      1> ct:run_test([{group,GroupsNamesOrPaths}, {case,Cases}]).

      Parameter group_names_or_paths specifies one or more group names and/or one or +syntax for specifying groups on the command line is as follows:

      $ ct_run -group <group_names_or_paths> [-case <cases>]

      The syntax in the Erlang shell is as follows:

      1> ct:run_test([{group,GroupsNamesOrPaths}, {case,Cases}]).

      Parameter group_names_or_paths specifies one or more group names and/or one or more group paths. At startup, Common Test searches for matching groups in the group definitions tree (that is, the list returned from Suite:groups/0; for details, see section Test Case Groups.

      Given a group name, say g, Common Test searches for all paths leading to @@ -168,30 +168,30 @@ paths if an incomplete group path is specified.

    Note

    Group names and group paths can be combined with parameter group_names_or_paths. Each element is treated as an individual specification in combination with parameter cases. The following examples illustrates -this.

    Examples:

    -module(x_SUITE).
    +this.

    Examples:

    -module(x_SUITE).
     ...
     %% The group definitions:
    -groups() ->
    -  [{top1,[],[tc11,tc12,
    -             {sub11,[],[tc12,tc13]},
    -             {sub12,[],[tc14,tc15,
    -       		 {sub121,[],[tc12,tc16]}]}]},
    -
    -   {top2,[],[{group,sub21},{group,sub22}]},
    -   {sub21,[],[tc21,{group,sub2X2}]},
    -   {sub22,[],[{group,sub221},tc21,tc22,{group,sub2X2}]},
    -   {sub221,[],[tc21,tc23]},
    -   {sub2X2,[],[tc21,tc24]}].

    The following executes two tests, one for all cases and all subgroups under -top1, and one for all under top2:

    $ ct_run -suite "x_SUITE" -group all
    1> ct:run_test([{suite,"x_SUITE"}, {group,all}]).

    Using -group top1 top2, or {group,[top1,top2]} gives the same result.

    The following executes one test for all cases and subgroups under top1:

    $ ct_run -suite "x_SUITE" -group top1
    1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}]).

    The following runs a test executing tc12 in top1 and any subgroup under -top1 where it can be found (sub11 and sub121):

    $ ct_run -suite "x_SUITE" -group top1 -case tc12
    1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}, {testcase,[tc12]}]).

    The following executes tc12 only in group top1:

    $ ct_run -suite "x_SUITE" -group [top1] -case tc12
    1> ct:run_test([{suite,"x_SUITE"}, {group,[[top1]]}, {testcase,[tc12]}]).

    The following searches top1 and all its subgroups for tc16 resulting in that -this test case executes in group sub121:

    $ ct_run -suite "x_SUITE" -group top1 -case tc16
    1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}, {testcase,[tc16]}]).

    Using the specific path -group [sub121] or {group,[[sub121]]} gives the same +groups() -> + [{top1,[],[tc11,tc12, + {sub11,[],[tc12,tc13]}, + {sub12,[],[tc14,tc15, + {sub121,[],[tc12,tc16]}]}]}, + + {top2,[],[{group,sub21},{group,sub22}]}, + {sub21,[],[tc21,{group,sub2X2}]}, + {sub22,[],[{group,sub221},tc21,tc22,{group,sub2X2}]}, + {sub221,[],[tc21,tc23]}, + {sub2X2,[],[tc21,tc24]}].

    The following executes two tests, one for all cases and all subgroups under +top1, and one for all under top2:

    $ ct_run -suite "x_SUITE" -group all
    1> ct:run_test([{suite,"x_SUITE"}, {group,all}]).

    Using -group top1 top2, or {group,[top1,top2]} gives the same result.

    The following executes one test for all cases and subgroups under top1:

    $ ct_run -suite "x_SUITE" -group top1
    1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}]).

    The following runs a test executing tc12 in top1 and any subgroup under +top1 where it can be found (sub11 and sub121):

    $ ct_run -suite "x_SUITE" -group top1 -case tc12
    1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}, {testcase,[tc12]}]).

    The following executes tc12 only in group top1:

    $ ct_run -suite "x_SUITE" -group [top1] -case tc12
    1> ct:run_test([{suite,"x_SUITE"}, {group,[[top1]]}, {testcase,[tc12]}]).

    The following searches top1 and all its subgroups for tc16 resulting in that +this test case executes in group sub121:

    $ ct_run -suite "x_SUITE" -group top1 -case tc16
    1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}, {testcase,[tc16]}]).

    Using the specific path -group [sub121] or {group,[[sub121]]} gives the same result in this example.

    The following executes two tests, one including all cases and subgroups under -sub12, and one with only the test cases in sub12:

    $ ct_run -suite "x_SUITE" -group sub12 [sub12]
    1> ct:run_test([{suite,"x_SUITE"}, {group,[sub12,[sub12]]}]).

    In the following example, Common Test finds and executes two tests, one for +sub12, and one with only the test cases in sub12:

    $ ct_run -suite "x_SUITE" -group sub12 [sub12]
    1> ct:run_test([{suite,"x_SUITE"}, {group,[sub12,[sub12]]}]).

    In the following example, Common Test finds and executes two tests, one for the path from top2 to sub2X2 through sub21, and one from top2 to -sub2X2 through sub22:

    $ ct_run -suite "x_SUITE" -group sub2X2
    1> ct:run_test([{suite,"x_SUITE"}, {group,[sub2X2]}]).

    In the following example, by specifying the unique path +sub2X2 through sub22:

    $ ct_run -suite "x_SUITE" -group sub2X2
    1> ct:run_test([{suite,"x_SUITE"}, {group,[sub2X2]}]).

    In the following example, by specifying the unique path top2 -> sub21 -> sub2X2, only one test is executed. The second possible path, -from top2 to sub2X2 (from the former example) is discarded:

    $ ct_run -suite "x_SUITE" -group [sub21,sub2X2]
    1> ct:run_test([{suite,"x_SUITE"}, {group,[[sub21,sub2X2]]}]).

    The following executes only the test cases for sub22 and in reverse order -compared to the group definition:

    $ ct_run -suite "x_SUITE" -group [sub22] -case tc22 tc21
    1> ct:run_test([{suite,"x_SUITE"}, {group,[[sub22]]}, {testcase,[tc22,tc21]}]).

    If a test case belonging to a group (according to the group definition) is +from top2 to sub2X2 (from the former example) is discarded:

    $ ct_run -suite "x_SUITE" -group [sub21,sub2X2]
    1> ct:run_test([{suite,"x_SUITE"}, {group,[[sub21,sub2X2]]}]).

    The following executes only the test cases for sub22 and in reverse order +compared to the group definition:

    $ ct_run -suite "x_SUITE" -group [sub22] -case tc22 tc21
    1> ct:run_test([{suite,"x_SUITE"}, {group,[[sub22]]}, {testcase,[tc22,tc21]}]).

    If a test case belonging to a group (according to the group definition) is executed without a group specification, that is, simply by (using the command line):

    $ ct_run -suite "my_SUITE" -case my_tc

    or (using the Erlang shell):

    1> ct:run_test([{suite,"my_SUITE"}, {testcase,my_tc}]).

    then Common Test ignores the group definition and executes the test case in the scope of the test suite only (no group configuration functions are called).

    The group specification feature, as presented in this section, can also be used @@ -213,12 +213,12 @@ configuration data with ct:require/1,2. This is equivalent to a require statement in the Test Suite Information Function or in the -Test Case Information Function.

    Example:

    1> ct:require(unix_telnet, unix).
    +Test Case Information Function.

    Example:

    1> ct:require(unix_telnet, unix).
     ok
    -2> ct_telnet:open(unix_telnet).
    -{ok,<0.105.0>}
    -4> ct_telnet:cmd(unix_telnet, "ls .").
    -{ok,["ls .","file1  ...",...]}

    Everything that Common Test normally prints in the test case logs, are in the +2> ct_telnet:open(unix_telnet). +{ok,<0.105.0>} +4> ct_telnet:cmd(unix_telnet, "ls ."). +{ok,["ls .","file1 ...",...]}

    Everything that Common Test normally prints in the test case logs, are in the interactive mode written to a log named ctlog.html in directory ct_run.<timestamp>. A link to this file is available in the file named last_interactive.html in the directory from which you execute ct_run. @@ -275,8 +275,8 @@ included specification can either be joined with the source specification or used to produce a separate test run (as with start flag/option join_specs above).

    Example:

    %% In specification file "a.spec"
    -{specs, join, ["b.spec", "c.spec"]}.
    -{specs, separate, ["d.spec", "e.spec"]}.
    +{specs, join, ["b.spec", "c.spec"]}.
    +{specs, separate, ["d.spec", "e.spec"]}.
     %% Config and test terms follow
     ...

    In this example, the test terms defined in files "b.spec" and "c.spec" are joined with the terms in source specification "a.spec" (if any). The inclusion @@ -326,154 +326,154 @@ available start flags (as most flags have a corresponding configuration term)

  • Logging (for terms verbosity, stylesheet, basic_html and esc_chars)
  • External Configuration Data (for terms config and userconfig)
  • Event Handling (for the -event_handler term)
  • Common Test Hooks (for term ct_hooks)
  • Configuration terms:

    {merge_tests, Bool}.
    +event_handler term)
  • Common Test Hooks (for term ct_hooks)
  • Configuration terms:

    {merge_tests, Bool}.
     
    -{define, Constant, Value}.
    +{define, Constant, Value}.
     
    -{specs, InclSpecsOption, TestSpecs}.
    +{specs, InclSpecsOption, TestSpecs}.
     
    -{node, NodeAlias, Node}.
    +{node, NodeAlias, Node}.
     
    -{init, InitOptions}.
    -{init, [NodeAlias], InitOptions}.
    +{init, InitOptions}.
    +{init, [NodeAlias], InitOptions}.
     
    -{label, Label}.
    -{label, NodeRefs, Label}.
    +{label, Label}.
    +{label, NodeRefs, Label}.
     
    -{verbosity, VerbosityLevels}.
    -{verbosity, NodeRefs, VerbosityLevels}.
    +{verbosity, VerbosityLevels}.
    +{verbosity, NodeRefs, VerbosityLevels}.
     
    -{stylesheet, CSSFile}.
    -{stylesheet, NodeRefs, CSSFile}.
    +{stylesheet, CSSFile}.
    +{stylesheet, NodeRefs, CSSFile}.
     
    -{silent_connections, ConnTypes}.
    -{silent_connections, NodeRefs, ConnTypes}.
    +{silent_connections, ConnTypes}.
    +{silent_connections, NodeRefs, ConnTypes}.
     
    -{multiply_timetraps, N}.
    -{multiply_timetraps, NodeRefs, N}.
    +{multiply_timetraps, N}.
    +{multiply_timetraps, NodeRefs, N}.
     
    -{scale_timetraps, Bool}.
    -{scale_timetraps, NodeRefs, Bool}.
    +{scale_timetraps, Bool}.
    +{scale_timetraps, NodeRefs, Bool}.
     
    -{cover, CoverSpecFile}.
    -{cover, NodeRefs, CoverSpecFile}.
    +{cover, CoverSpecFile}.
    +{cover, NodeRefs, CoverSpecFile}.
     
    -{cover_stop, Bool}.
    -{cover_stop, NodeRefs, Bool}.
    +{cover_stop, Bool}.
    +{cover_stop, NodeRefs, Bool}.
     
    -{include, IncludeDirs}.
    -{include, NodeRefs, IncludeDirs}.
    +{include, IncludeDirs}.
    +{include, NodeRefs, IncludeDirs}.
     
    -{auto_compile, Bool},
    -{auto_compile, NodeRefs, Bool},
    +{auto_compile, Bool},
    +{auto_compile, NodeRefs, Bool},
     
    -{abort_if_missing_suites, Bool},
    -{abort_if_missing_suites, NodeRefs, Bool},
    +{abort_if_missing_suites, Bool},
    +{abort_if_missing_suites, NodeRefs, Bool},
     
    -{config, ConfigFiles}.
    -{config, ConfigDir, ConfigBaseNames}.
    -{config, NodeRefs, ConfigFiles}.
    -{config, NodeRefs, ConfigDir, ConfigBaseNames}.
    +{config, ConfigFiles}.
    +{config, ConfigDir, ConfigBaseNames}.
    +{config, NodeRefs, ConfigFiles}.
    +{config, NodeRefs, ConfigDir, ConfigBaseNames}.
     
    -{userconfig, {CallbackModule, ConfigStrings}}.
    -{userconfig, NodeRefs, {CallbackModule, ConfigStrings}}.
    +{userconfig, {CallbackModule, ConfigStrings}}.
    +{userconfig, NodeRefs, {CallbackModule, ConfigStrings}}.
     
    -{logdir, LogDir}.
    -{logdir, NodeRefs, LogDir}.
    +{logdir, LogDir}.
    +{logdir, NodeRefs, LogDir}.
     
    -{logopts, LogOpts}.
    -{logopts, NodeRefs, LogOpts}.
    +{logopts, LogOpts}.
    +{logopts, NodeRefs, LogOpts}.
     
    -{create_priv_dir, PrivDirOption}.
    -{create_priv_dir, NodeRefs, PrivDirOption}.
    +{create_priv_dir, PrivDirOption}.
    +{create_priv_dir, NodeRefs, PrivDirOption}.
     
    -{event_handler, EventHandlers}.
    -{event_handler, NodeRefs, EventHandlers}.
    -{event_handler, EventHandlers, InitArgs}.
    -{event_handler, NodeRefs, EventHandlers, InitArgs}.
    +{event_handler, EventHandlers}.
    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/unix_telnet.xhtml differs (HTML document, ASCII text, with very long lines (1667))
    --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/unix_telnet.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/unix_telnet.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -23,14 +23,14 @@
     
           

    Callback module for ct_telnet, for connecting to a Telnet server on a UNIX -host.

    It requires the following entry in the configuration file:

    {unix,[{telnet,HostNameOrIpAddress},
    -       {port,PortNum},                 % optional
    -       {username,UserName},
    -       {password,Password},
    -       {keep_alive,Bool}]}.            % optional

    To communicate through Telnet to the host specified by HostNameOrIpAddress, +host.

    It requires the following entry in the configuration file:

    {unix,[{telnet,HostNameOrIpAddress},
    +       {port,PortNum},                 % optional
    +       {username,UserName},
    +       {password,Password},
    +       {keep_alive,Bool}]}.            % optional

    To communicate through Telnet to the host specified by HostNameOrIpAddress, use the interface functions in ct_telnet, for example, open(Name) and cmd(Name,Cmd).

    Name is the name you allocated to the Unix host in your require statement, -for example:

    suite() -> [{require,Name,{unix,[telnet]}}].

    or

    ct:require(Name,{unix,[telnet]}).

    The "keep alive" activity (that is, that Common Test sends NOP to the server +for example:

    suite() -> [{require,Name,{unix,[telnet]}}].

    or

    ct:require(Name,{unix,[telnet]}).

    The "keep alive" activity (that is, that Common Test sends NOP to the server every 10 seconds if the connection is idle) can be enabled or disabled for one particular connection as described here. It can be disabled for all connections using telnet_settings (see ct_telnet).

    The {port,PortNum} tuple is optional and if omitted, default Telnet port 23 is /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/write_test_chapter.xhtml differs (HTML document, ASCII text, with very long lines (1666)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/write_test_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/common_test.epub/OEBPS/write_test_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -122,29 +122,29 @@ system configuration files, the test case is skipped.

    A required variable can also be given a default value to be used if the variable is not found in any configuration file. To specify a default value, add a tuple of the form {default_config,ConfigVariableName,Value} to the -test case information list (the position in the list is irrelevant).

    Examples:

    testcase1() ->
    -    [{require, ftp},
    -     {default_config, ftp, [{ftp, "my_ftp_host"},
    -                            {username, "aladdin"},
    -                            {password, "sesame"}]}}].
    testcase2() ->
    -    [{require, unix_telnet, unix},
    -     {require, {unix, [telnet, username, password]}},
    -     {default_config, unix, [{telnet, "my_telnet_host"},
    -                             {username, "aladdin"},
    -                             {password, "sesame"}]}}].

    For more information about require, see section +test case information list (the position in the list is irrelevant).

    Examples:

    testcase1() ->
    +    [{require, ftp},
    +     {default_config, ftp, [{ftp, "my_ftp_host"},
    +                            {username, "aladdin"},
    +                            {password, "sesame"}]}}].
    testcase2() ->
    +    [{require, unix_telnet, unix},
    +     {require, {unix, [telnet, username, password]}},
    +     {default_config, unix, [{telnet, "my_telnet_host"},
    +                             {username, "aladdin"},
    +                             {password, "sesame"}]}}].

    For more information about require, see section Requiring and Reading Configuration Data in section External Configuration Data and function ct:require/1/2.

    Note

    Specifying a default value for a required variable can result in a test case always getting executed. This might not be a desired behavior.

    If timetrap or require, or both, is not set specifically for a particular test case, default values specified by function -suite/0 are used.

    Tags other than the earlier mentioned are ignored by the test server.

    An example of a test case information function follows:

    reboot_node() ->
    -    [
    -     {timetrap,{seconds,60}},
    -     {require,interfaces},
    -     {userdata,
    -         [{description,"System Upgrade: RpuAddition Normal RebootNode"},
    -          {fts,"http://someserver.ericsson.se/test_doc4711.pdf"}]}
    -    ].

    Test Suite Information Function

    Function suite/0 can, for example, be used in a test +suite/0 are used.

    Tags other than the earlier mentioned are ignored by the test server.

    An example of a test case information function follows:

    reboot_node() ->
    +    [
    +     {timetrap,{seconds,60}},
    +     {require,interfaces},
    +     {userdata,
    +         [{description,"System Upgrade: RpuAddition Normal RebootNode"},
    +          {fts,"http://someserver.ericsson.se/test_doc4711.pdf"}]}
    +    ].

    Test Suite Information Function

    Function suite/0 can, for example, be used in a test suite module to set a default timetrap value and to require external configuration data. If a test case, or a group information function also specifies any of the information tags, it overrides the default values set by @@ -152,14 +152,14 @@ Test Case Information Function and Test Case Groups.

    The following options can also be specified with the suite information list:

    An example of the suite information function follows:

    suite() ->
    -    [
    -     {timetrap,{minutes,10}},
    -     {require,global_names},
    -     {userdata,[{info,"This suite tests database transactions."}]},
    -     {silent_connections,[telnet]},
    -     {stylesheet,"db_testing.css"}
    -    ].

    Test Case Groups

    A test case group is a set of test cases sharing configuration functions and +Silent Connections

    An example of the suite information function follows:

    suite() ->
    +    [
    +     {timetrap,{minutes,10}},
    +     {require,global_names},
    +     {userdata,[{info,"This suite tests database transactions."}]},
    +     {silent_connections,[telnet]},
    +     {stylesheet,"db_testing.css"}
    +    ].

    Test Case Groups

    A test case group is a set of test cases sharing configuration functions and execution properties. Test case groups are defined by function groups/0 that should return a term having the following syntax:

    groups() -> GroupDefs
    @@ -175,20 +175,20 @@
     TCRepeatProps = [{repeat,N} | {repeat_until_ok,N} | {repeat_until_fail,N}]

    GroupName is the name of the group and must be unique within the test suite module. Groups can be nested, by including a group definition within the GroupsAndTestCases list of another group. Properties is the list of -execution properties for the group. The possible values are as follows:

    Properties = [parallel | sequence | Shuffle | {GroupRepeatType,N}]
    -Shuffle = shuffle | {shuffle,Seed}
    -Seed = {integer(),integer(),integer()}
    +execution properties for the group. The possible values are as follows:

    Properties = [parallel | sequence | Shuffle | {GroupRepeatType,N}]
    +Shuffle = shuffle | {shuffle,Seed}
    +Seed = {integer(),integer(),integer()}
     GroupRepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
                       repeat_until_any_ok | repeat_until_any_fail
    -N = integer() | forever

    Explanations:

    • parallel - Common Test executes all test cases in the group in +N = integer() | forever

    Explanations:

    • parallel - Common Test executes all test cases in the group in parallel.

    • sequence - The cases are executed in a sequence as described in section Sequences in section Dependencies Between Test Cases and Suites.

    • shuffle - The cases in the group are executed in random order.

    • repeat, repeat_until_* - Orders Common Test to repeat execution of all the cases in the group a given number of times, or until any, or all, cases -fail or succeed.

    Example:

    groups() -> [{group1, [parallel], [test1a,test1b]},
    -             {group2, [shuffle,sequence], [test2a,test2b,test2c]}].

    To specify in which order groups are to be executed (also with respect to test +fail or succeed.

    Example:

    groups() -> [{group1, [parallel], [test1a,test1b]},
    +             {group2, [shuffle,sequence], [test2a,test2b,test2c]}].

    To specify in which order groups are to be executed (also with respect to test cases that are not part of any group), add tuples on the form -{group,GroupName} to the all/0 list.

    Example:

    all() -> [testcase1, {group,group1}, {testcase,testcase2,[{repeat,10}]}, {group,group2}].

    Execution properties with a group tuple in all/0: +{group,GroupName} to the all/0 list.

    Example:

    all() -> [testcase1, {group,group1}, {testcase,testcase2,[{repeat,10}]}, {group,group2}].

    Execution properties with a group tuple in all/0: {group,GroupName,Properties} can also be specified. These properties override those specified in the group definition (see groups/0 earlier). This way, the same set of tests can be run, but with different properties, without having to @@ -197,33 +197,33 @@ SubGroups is a list of tuples, {GroupName,Properties} or {GroupName,Properties,SubGroups} representing the subgroups. Any subgroups defined in groups/0 for a group, that are not specified in the SubGroups -list, executes with their predefined properties.

    Example:

    groups() -> [{tests1, [], [{tests2, [], [t2a,t2b]},
    -                          {tests3, [], [t31,t3b]}]}].

    To execute group tests1 twice with different properties for tests2 each -time:

    all() ->
    -   [{group, tests1, default, [{tests2, [parallel]}]},
    -    {group, tests1, default, [{tests2, [shuffle,{repeat,10}]}]}].

    This is equivalent to the following specification:

    all() ->
    -   [{group, tests1, default, [{tests2, [parallel]},
    -                              {tests3, default}]},
    -    {group, tests1, default, [{tests2, [shuffle,{repeat,10}]},
    -                              {tests3, default}]}].

    Value default states that the predefined properties are to be used.

    The following example shows how to override properties in a scenario with deeply -nested groups:

    groups() ->
    -   [{tests1, [], [{group, tests2}]},
    -    {tests2, [], [{group, tests3}]},
    -    {tests3, [{repeat,2}], [t3a,t3b,t3c]}].
    +list, executes with their predefined properties.

    Example:

    groups() -> [{tests1, [], [{tests2, [], [t2a,t2b]},
    +                          {tests3, [], [t31,t3b]}]}].

    To execute group tests1 twice with different properties for tests2 each +time:

    all() ->
    +   [{group, tests1, default, [{tests2, [parallel]}]},
    +    {group, tests1, default, [{tests2, [shuffle,{repeat,10}]}]}].

    This is equivalent to the following specification:

    all() ->
    +   [{group, tests1, default, [{tests2, [parallel]},
    +                              {tests3, default}]},
    +    {group, tests1, default, [{tests2, [shuffle,{repeat,10}]},
    +                              {tests3, default}]}].

    Value default states that the predefined properties are to be used.

    The following example shows how to override properties in a scenario with deeply +nested groups:

    groups() ->
    +   [{tests1, [], [{group, tests2}]},
    +    {tests2, [], [{group, tests3}]},
    +    {tests3, [{repeat,2}], [t3a,t3b,t3c]}].
     
    -all() ->
    -   [{group, tests1, default,
    -     [{tests2, default,
    -       [{tests3, [parallel,{repeat,100}]}]}]}].

    For ease of readability, all syntax definitions can be replaced by a function -call whose return value should match the expected syntax case.

    Example:

    all() ->
    -   [{group, tests1, default, test_cases()},
    -    {group, tests1, default, [shuffle_test(),
    -                              {tests3, default}]}].
    -test_cases() ->
    -   [{tests2, [parallel]}, {tests3, default}].
    +all() ->
    +   [{group, tests1, default,
    +     [{tests2, default,
    +       [{tests3, [parallel,{repeat,100}]}]}]}].

    For ease of readability, all syntax definitions can be replaced by a function +call whose return value should match the expected syntax case.

    Example:

    all() ->
    +   [{group, tests1, default, test_cases()},
    +    {group, tests1, default, [shuffle_test(),
    +                              {tests3, default}]}].
    +test_cases() ->
    +   [{tests2, [parallel]}, {tests3, default}].
     
    -shuffle_test() ->
    -   {tests2, [shuffle,{repeat,10}]}.

    The described syntax can also be used in test specifications to change group +shuffle_test() -> + {tests2, [shuffle,{repeat,10}]}.

    The described syntax can also be used in test specifications to change group properties at the time of execution, without having to edit the test suite. For more information, see section Test Specifications in section @@ -249,13 +249,13 @@ bottom of the log for end_per_group/2.

    Test case groups can be nested so sets of groups can be configured with the same init_per_group/2 and end_per_group/2 functions. Nested groups can be defined by including a group definition, or a group name reference, in the test case -list of another group.

    Example:

    groups() -> [{group1, [shuffle], [test1a,
    -                                  {group2, [], [test2a,test2b]},
    -                                  test1b]},
    -             {group3, [], [{group,group4},
    -                           {group,group5}]},
    -             {group4, [parallel], [test4a,test4b]},
    -             {group5, [sequence], [test5a,test5b,test5c]}].

    In the previous example, if all/0 returns group name references in the order +list of another group.

    Example:

    groups() -> [{group1, [shuffle], [test1a,
    +                                  {group2, [], [test2a,test2b]},
    +                                  test1b]},
    +             {group3, [], [{group,group4},
    +                           {group,group5}]},
    +             {group4, [parallel], [test4a,test4b]},
    +             {group5, [sequence], [test5a,test5b,test5c]}].

    In the previous example, if all/0 returns group name references in the order [{group,group1},{group,group3}], the order of the configuration functions and test cases becomes the following (notice that init_per_testcase/2 and end_per_testcase/2: are also always called, but not included in this example @@ -310,25 +310,25 @@ account by Common Test when evaluating if execution of a group is to be repeated or not (unless the basic repeat property is used).

    The value of tc_group_properties is a list of status tuples, each with the key ok, skipped, and failed. The value of a status tuple is a list with names -of test cases that have been executed with the corresponding status as result.

    The following is an example of how to return the status from a group:

    end_per_group(_Group, Config) ->
    -    Status = proplists:get_value(tc_group_result, Config),
    -    case proplists:get_value(failed, Status) of
    -        [] ->                                   % no failed cases
    -            {return_group_result,ok};
    +of test cases that have been executed with the corresponding status as result.

    The following is an example of how to return the status from a group:

    end_per_group(_Group, Config) ->
    +    Status = proplists:get_value(tc_group_result, Config),
    +    case proplists:get_value(failed, Status) of
    +        [] ->                                   % no failed cases
    +            {return_group_result,ok};
             _Failed ->                              % one or more failed
    -            {return_group_result,failed}
    +            {return_group_result,failed}
         end.

    It is also possible, in end_per_group/2, to check the status of a subgroup (maybe to determine what status the current group is to return). This is as /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/config_file_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1269)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/config_file_chapter.html 2026-08-21 04:00:19.079292522 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/config_file_chapter.html 2026-08-21 04:00:19.079292522 +0000 @@ -94,8 +94,8 @@ configuration files or strings that Common Test reads before the start of a test run. External configuration data makes it possible to change test properties without modifying the test suites using the data. Examples of -configuration data follows:

    • Addresses to the test plant or other instruments
    • User login information
    • Names of files needed by the test
    • Names of programs to be executed during the test
    • Any other variable needed by the test

    Syntax

    A configuration file can contain any number of elements of the type:

    {CfgVarName,Value}.

    where

    CfgVarName = atom()
    -Value = term() | [{CfgVarName,Value}]

    Requiring and Reading Configuration Data

    In a test suite, one must require that a configuration variable (CfgVarName +configuration data follows:

    • Addresses to the test plant or other instruments
    • User login information
    • Names of files needed by the test
    • Names of programs to be executed during the test
    • Any other variable needed by the test

    Syntax

    A configuration file can contain any number of elements of the type:

    {CfgVarName,Value}.

    where

    CfgVarName = atom()
    +Value = term() | [{CfgVarName,Value}]

    Requiring and Reading Configuration Data

    In a test suite, one must require that a configuration variable (CfgVarName in the previous definition) exists before attempting to read the associated value in a test case or configuration function.

    require is an assert statement, which can be part of the Test Suite Information Function or @@ -116,13 +116,13 @@ any number of alias names, but each name must be unique within the same test suite. The two main uses for alias names follows:

    • To identify connections (described later).
    • To help adapt configuration data to a test suite (or test case) and improve readability.

    To read the value of a configuration variable, use function -get_config/1,2,3.

    Example:

    suite() ->
    -    [{require, domain, 'CONN_SPEC_DNS_SUFFIX'}].
    +get_config/1,2,3.

    Example:

    suite() ->
    +    [{require, domain, 'CONN_SPEC_DNS_SUFFIX'}].
     
     ...
     
    -testcase(Config) ->
    -    Domain = ct:get_config(domain),
    +testcase(Config) ->
    +    Domain = ct:get_config(domain),
         ...

    Using Configuration Variables Defined in Multiple Files

    If a configuration variable is defined in multiple files and you want to access all possible values, use function ct:get_config/3 and specify all in the options list. The values are then returned in a list and the order of the @@ -171,11 +171,11 @@ </ftp_host> <lm_directory>"/test/loadmodules"</lm_directory> </config>

    Once read, this file produces the same configuration variables as the following -text file:

    {ftp_host, [{ftp,"targethost"},
    -            {username,"tester"},
    -            {password,"letmein"}]}.
    +text file:

    {ftp_host, [{ftp,"targethost"},
    +            {username,"tester"},
    +            {password,"letmein"}]}.
     
    -{lm_directory, "/test/loadmodules"}.

    Implement a User-Specific Handler

    The user-specific handler can be written to handle special configuration file +{lm_directory, "/test/loadmodules"}.

    Implement a User-Specific Handler

    The user-specific handler can be written to handle special configuration file formats. The parameter can be either file names or configuration strings (the empty list is valid).

    The callback module implementing the handler is responsible for checking the correctness of configuration strings.

    To validate the configuration strings, the callback module is to have function @@ -188,130 +188,130 @@ data being reloaded during test execution. The input argument is the same as for function check_parameter/1.

    The return value is to be either of the following:

    • {ok, Config} - if the configuration variables are read successfully.
    • {error, {Error, ErrorDetails}} - if the callback module fails to proceed with the specified configuration parameters.

    Config is the proper Erlang key-value list, with possible key-value sublists -as values, like the earlier configuration file example:

    [{ftp_host, [{ftp, "targethost"}, {username, "tester"}, {password, "letmein"}]},
    - {lm_directory, "/test/loadmodules"}]

    Examples of Configuration Data Handling

    A configuration file for using the FTP client to access files on a remote host -can look as follows:

    {ftp_host, [{ftp,"targethost"},
    -            {username,"tester"},
    -            {password,"letmein"}]}.
    +as values, like the earlier configuration file example:

    [{ftp_host, [{ftp, "targethost"}, {username, "tester"}, {password, "letmein"}]},
    + {lm_directory, "/test/loadmodules"}]

    Examples of Configuration Data Handling

    A configuration file for using the FTP client to access files on a remote host +can look as follows:

    {ftp_host, [{ftp,"targethost"},
    +            {username,"tester"},
    +            {password,"letmein"}]}.
     
    -{lm_directory, "/test/loadmodules"}.

    The XML version shown earlier can also be used, but it is to be explicitly +{lm_directory, "/test/loadmodules"}.

    The XML version shown earlier can also be used, but it is to be explicitly specified that the ct_config_xml callback module is to be used by Common Test.

    The following is an example of how to assert that the configuration data is -available and can be used for an FTP session:

    init_per_testcase(ftptest, Config) ->
    -    {ok,_} = ct_ftp:open(ftp),
    +available and can be used for an FTP session:

    init_per_testcase(ftptest, Config) ->
    +    {ok,_} = ct_ftp:open(ftp),
         Config.
     
    -end_per_testcase(ftptest, _Config) ->
    -    ct_ftp:close(ftp).
    +end_per_testcase(ftptest, _Config) ->
    +    ct_ftp:close(ftp).
     
    -ftptest() ->
    -    [{require,ftp,ftp_host},
    -     {require,lm_directory}].
    -
    -ftptest(Config) ->
    -    Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
    -    Local = filename:join(proplists:get_value(priv_dir,Config), "loadmodule"),
    -    ok = ct_ftp:recv(ftp, Remote, Local),
    +ftptest() ->
    +    [{require,ftp,ftp_host},
    +     {require,lm_directory}].
    +
    +ftptest(Config) ->
    +    Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
    +    Local = filename:join(proplists:get_value(priv_dir,Config), "loadmodule"),
    +    ok = ct_ftp:recv(ftp, Remote, Local),
         ...

    The following is an example of how the functions in the previous example can be -rewritten if it is necessary to open multiple connections to the FTP server:

    init_per_testcase(ftptest, Config) ->
    -    {ok,Handle1} = ct_ftp:open(ftp_host),
    -    {ok,Handle2} = ct_ftp:open(ftp_host),
    -    [{ftp_handles,[Handle1,Handle2]} | Config].
    -
    -end_per_testcase(ftptest, Config) ->
    -    lists:foreach(fun(Handle) -> ct_ftp:close(Handle) end,
    -                  proplists:get_value(ftp_handles,Config)).
    -
    -ftptest() ->
    -    [{require,ftp_host},
    -     {require,lm_directory}].
    -
    -ftptest(Config) ->
    -    Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
    -    Local = filename:join(proplists:get_value(priv_dir,Config), "loadmodule"),
    -    [Handle | MoreHandles] = proplists:get_value(ftp_handles,Config),
    -    ok = ct_ftp:recv(Handle, Remote, Local),
    +rewritten if it is necessary to open multiple connections to the FTP server:

    init_per_testcase(ftptest, Config) ->
    +    {ok,Handle1} = ct_ftp:open(ftp_host),
    +    {ok,Handle2} = ct_ftp:open(ftp_host),
    +    [{ftp_handles,[Handle1,Handle2]} | Config].
    +
    +end_per_testcase(ftptest, Config) ->
    +    lists:foreach(fun(Handle) -> ct_ftp:close(Handle) end,
    +                  proplists:get_value(ftp_handles,Config)).
    +
    +ftptest() ->
    +    [{require,ftp_host},
    +     {require,lm_directory}].
    +
    +ftptest(Config) ->
    +    Remote = filename:join(ct:get_config(lm_directory), "loadmodX"),
    +    Local = filename:join(proplists:get_value(priv_dir,Config), "loadmodule"),
    +    [Handle | MoreHandles] = proplists:get_value(ftp_handles,Config),
    +    ok = ct_ftp:recv(Handle, Remote, Local),
         ...

    Example of User-Specific Configuration Handler

    A simple configuration handling driver, asking an external server for -configuration data, can be implemented as follows:

    -module(config_driver).
    --export([read_config/1, check_parameter/1]).
    +configuration data, can be implemented as follows:

    -module(config_driver).
    +-export([read_config/1, check_parameter/1]).
     
    -read_config(ServerName)->
    -    ServerModule = list_to_atom(ServerName),
    -    ServerModule:start(),
    -    ServerModule:get_config().
    -
    -check_parameter(ServerName)->
    -    ServerModule = list_to_atom(ServerName),
    -    case code:is_loaded(ServerModule) of
    -        {file, _}->
    -            {ok, {config, ServerName}};
    +read_config(ServerName)->
    +    ServerModule = list_to_atom(ServerName),
    +    ServerModule:start(),
    +    ServerModule:get_config().
    +
    +check_parameter(ServerName)->
    +    ServerModule = list_to_atom(ServerName),
    +    case code:is_loaded(ServerModule) of
    +        {file, _}->
    +            {ok, {config, ServerName}};
             false->
    -            case code:load_file(ServerModule) of
    -                {module, ServerModule}->
    -                    {ok, {config, ServerName}};
    -                {error, nofile}->
    -                    {error, {wrong_config, "File not found: " ++ ServerName ++ ".beam"}}
    +            case code:load_file(ServerModule) of
    +                {module, ServerModule}->
    +                    {ok, {config, ServerName}};
    +                {error, nofile}->
    +                    {error, {wrong_config, "File not found: " ++ ServerName ++ ".beam"}}
                 end
         end.

    The configuration string for this driver can be config_server, if the config_server.erl module that follows is compiled and exists in the code path -during test execution:

    -module(config_server).
    --export([start/0, stop/0, init/1, get_config/0, loop/0]).
    +during test execution:

    -module(config_server).
    +-export([start/0, stop/0, init/1, get_config/0, loop/0]).
     
    --define(REGISTERED_NAME, ct_test_config_server).
    +-define(REGISTERED_NAME, ct_test_config_server).
     
    -start()->
    -    case whereis(?REGISTERED_NAME) of
    +start()->
    +    case whereis(?REGISTERED_NAME) of
             undefined->
    -            spawn(?MODULE, init, [?REGISTERED_NAME]),
    -            wait();
    +            spawn(?MODULE, init, [?REGISTERED_NAME]),
    +            wait();
             _Pid->
             ok
         end,
         ?REGISTERED_NAME.
     
    -init(Name)->
    -    register(Name, self()),
    -    loop().
    +init(Name)->
    +    register(Name, self()),
    +    loop().
     
    -get_config()->
    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/cover_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1159))
    --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/cover_chapter.html	2026-08-21 04:00:19.098292646 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/cover_chapter.html	2026-08-21 04:00:19.099292652 +0000
    @@ -135,44 +135,44 @@
     Running Tests and Analyzing Results).

    The Cover Specification File

    General Config

    Here follows the general configuration terms that are allowed in a cover specification file:

    %% List of Nodes on which cover will be active during test.
     %% Nodes = [atom()]
    -{nodes, Nodes}.
    +{nodes, Nodes}.
     
     %% Files with previously exported cover data to include in analysis.
     %% CoverDataFiles = [string()]
    -{import, CoverDataFiles}.
    +{import, CoverDataFiles}.
     
     %% Cover data file to export from this session.
     %% CoverDataFile = string()
    -{export, CoverDataFile}.
    +{export, CoverDataFile}.
     
     %% Cover analysis level.
     %% Level = details | overview
    -{level, Level}.
    +{level, Level}.
     
     %% Directories to include in cover.
     %% Dirs = [string()]
    -{incl_dirs, Dirs}.
    +{incl_dirs, Dirs}.
     
     %% Directories, including subdirectories, to include.
    -{incl_dirs_r, Dirs}.
    +{incl_dirs_r, Dirs}.
     
     %% Specific modules to include in cover.
     %% Mods = [atom()]
    -{incl_mods, Mods}.
    +{incl_mods, Mods}.
     
     %% Directories to exclude in cover.
    -{excl_dirs, Dirs}.
    +{excl_dirs, Dirs}.
     
     %% Directories, including subdirectories, to exclude.
    -{excl_dirs_r, Dirs}.
    +{excl_dirs_r, Dirs}.
     
     %% Specific modules to exclude in cover.
    -{excl_mods, Mods}.
    +{excl_mods, Mods}.
     
     %% Cross cover compilation
     %% Tag = atom(), an identifier for a test run
     %% Mod = [atom()], modules to compile for accumulated analysis
    -{cross,[{Tag,Mods}]}.

    The terms incl_dirs_r and excl_dirs_r tell Common Test to search the +{cross,[{Tag,Mods}]}.

    The terms incl_dirs_r and excl_dirs_r tell Common Test to search the specified directories recursively and include or exclude any module found during the search. The terms incl_dirs and excl_dirs result in a non-recursive search for modules (that is, only modules found in the specified directories are @@ -181,7 +181,7 @@ recompile the modules. It is not sufficient to specify these directories in the cover specification file for Common Test.

    OTP application Config

    When using a cover specification in the testing of an OTP application itself, there is a special incl_app directive that includes the applications modules for -the cover compilation.

    {incl_app, AppName, Cover :: overview | details}.

    Note

    If you desire to also use some other general cover configuration together with +the cover compilation.

    {incl_app, AppName, Cover :: overview | details}.

    Note

    If you desire to also use some other general cover configuration together with this option you should insert the AppName in between the option and its value creating a three tuple.

    Cross Cover Analysis

    The cross cover mechanism allows cover analysis of modules across multiple tests. It is useful if some code, for example, a library module, is used by many @@ -202,7 +202,7 @@ {cross,[{s1,[m1]}]}.

    Then m1 is cover compiled in test run s2, but not shown in the coverage log. Instead, if ct_cover:cross_cover_analyse/2 is called after both s1 and s2 test runs are completed, the accumulated result for m1 is available in the -cross cover log for test run s1.

    The call to the analyze function must be as follows:

    ct_cover:cross_cover_analyse(Level, [{s1,S1LogDir},{s2,S2LogDir}]).

    Here, S1LogDir and S2LogDir are the directories named <TestName>.logs for +cross cover log for test run s1.

    The call to the analyze function must be as follows:

    ct_cover:cross_cover_analyse(Level, [{s1,S1LogDir},{s2,S2LogDir}]).

    Here, S1LogDir and S2LogDir are the directories named <TestName>.logs for each test respectively.

    Notice the tags s1 and s2, which are used in the cover specification file and in the call to ct_cover:cross_cover_analyse/2. The purpose of these is only to map the modules specified in the cover specification to the log /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct.html 2026-08-21 04:00:19.141292925 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct.html 2026-08-21 04:00:19.142292932 +0000 @@ -1949,17 +1949,17 @@

    Reads configuration data values.

    Returns the matching values or configuration elements, given a configuration variable key or its associated name (if one has been specified with -ct:require/2 or a require statement).

    Example:

    Given the following configuration file:

    {unix,[{telnet,IpAddr},
    -       {user,[{username,Username},
    -              {password,Password}]}]}.

    Then:

    ct:get_config(unix,Default) -> [{telnet,IpAddr},
    - {user, [{username,Username}, {password,Password}]}]
    -ct:get_config({unix,telnet},Default) -> IpAddr
    -ct:get_config({unix,user,username},Default) -> Username
    -ct:get_config({unix,ftp},Default) -> Default
    -ct:get_config(unknownkey,Default) -> Default

    If a configuration variable key has been associated with a name (by +ct:require/2 or a require statement).

    Example:

    Given the following configuration file:

    {unix,[{telnet,IpAddr},
    +       {user,[{username,Username},
    +              {password,Password}]}]}.

    Then:

    ct:get_config(unix,Default) -> [{telnet,IpAddr},
    + {user, [{username,Username}, {password,Password}]}]
    +ct:get_config({unix,telnet},Default) -> IpAddr
    +ct:get_config({unix,user,username},Default) -> Username
    +ct:get_config({unix,ftp},Default) -> Default
    +ct:get_config(unknownkey,Default) -> Default

    If a configuration variable key has been associated with a name (by ct:require/2 or a require statement), the name can be used -instead of the key to read the value:

    ct:require(myuser,{unix,user}) -> ok.
    -ct:get_config(myuser,Default) -> [{username,Username}, {password,Password}]

    If a configuration variable is defined in multiple files, use option all to +instead of the key to read the value:

    ct:require(myuser,{unix,user}) -> ok.
    +ct:get_config(myuser,Default) -> [{username,Username}, {password,Password}]

    If a configuration variable is defined in multiple files, use option all to access all possible values. The values are returned in a list. The order of the elements corresponds to the order that the configuration files were specified at startup.

    If configuration elements (key-value tuples) are to be returned as result @@ -1997,7 +1997,7 @@

    Gets a reference to the Common Test event manager. The reference can be used -to, for example, add a user-specific event handler while tests are running.

    Example:

    gen_event:add_handler(ct:get_event_mgr_ref(), my_ev_h, [])
    +to, for example, add a user-specific event handler while tests are running.

    Example:

    gen_event:add_handler(ct:get_event_mgr_ref(), my_ev_h, [])
    @@ -2285,7 +2285,7 @@ -

    Installs configuration files and event handlers.

    Run this function once before the first test.

    Example:

    install([{config,["config_node.ctc","config_user.ctc"]}])

    This function is automatically run by program ct_run.

    +

    Installs configuration files and event handlers.

    Run this function once before the first test.

    Example:

    install([{config,["config_node.ctc","config_user.ctc"]}])

    This function is automatically run by program ct_run.

    @@ -3122,7 +3122,7 @@

    Checks if the required configuration is available. Arbitrarily deep tuples can be specified as Required. Only the last element of the tuple can be a list of -SubKeys.

    Example 1. Require the variable myvar:

    ok = ct:require(myvar).

    In this case the configuration file must at least contain:

    {myvar,Value}.

    Example 2. Require key myvar with subkeys sub1 and sub2:

    ok = ct:require({myvar,[sub1,sub2]}).

    In this case the configuration file must at least contain:

    {myvar,[{sub1,Value},{sub2,Value}]}.

    Example 3. Require key myvar with subkey sub1 with subsub1:

    ok = ct:require({myvar,sub1,sub2}).

    In this case the configuration file must at least contain:

    {myvar,[{sub1,[{sub2,Value}]}]}.

    See also ct:get_config/1, +SubKeys.

    Example 1. Require the variable myvar:

    ok = ct:require(myvar).

    In this case the configuration file must at least contain:

    {myvar,Value}.

    Example 2. Require key myvar with subkeys sub1 and sub2:

    ok = ct:require({myvar,[sub1,sub2]}).

    In this case the configuration file must at least contain:

    {myvar,[{sub1,Value},{sub2,Value}]}.

    Example 3. Require key myvar with subkey sub1 with subsub1:

    ok = ct:require({myvar,sub1,sub2}).

    In this case the configuration file must at least contain:

    {myvar,[{sub1,[{sub2,Value}]}]}.

    See also ct:get_config/1, ct:get_config/2, ct:get_config/3, ct:require/2.

    @@ -3164,8 +3164,8 @@ that the value of the element can be read with ct:get_config/1,2 provided Name is used instead of the whole Required term.

    Example:

    Require one node with a Telnet connection and an FTP connection. Name the node -a:

    ok = ct:require(a,{machine,node}).

    All references to this node can then use the node name. For example, a file over -FTP is fetched like follows:

    ok = ct:ftp_get(a,RemoteFile,LocalFile).

    For this to work, the configuration file must at least contain:

    {machine,[{node,[{telnet,IpAddr},{ftp,IpAddr}]}]}.

    Note

    The behavior of this function changed radically in Common Test 1.6.2. To +a:

    ok = ct:require(a,{machine,node}).

    All references to this node can then use the node name. For example, a file over +FTP is fetched like follows:

    ok = ct:ftp_get(a,RemoteFile,LocalFile).

    For this to work, the configuration file must at least contain:

    {machine,[{node,[{telnet,IpAddr},{ftp,IpAddr}]}]}.

    Note

    The behavior of this function changed radically in Common Test 1.6.2. To keep some backwards compatibility, it is still possible to do: ct:require(a,{node,[telnet,ftp]}). This associates the name a with the top-level node entry. For this to work, the configuration file must at least @@ -3540,12 +3540,12 @@ the Erlang shell. The interactive mode can also be started from the OS command line with ct_run -shell [-config File...].

    If any functions (for example, Telnet or FTP) using "required configuration data" are to be called from the Erlang shell, configuration data must first be -required with ct:require/2.

    Example:

    > ct:require(unix_telnet, unix).
    +required with ct:require/2.

    Example:

    > ct:require(unix_telnet, unix).
     ok
    -> ct_telnet:open(unix_telnet).
    -{ok,<0.105.0>}
    -> ct_telnet:cmd(unix_telnet, "ls .").
    -{ok,["ls","file1  ...",...]}
    +>
    ct_telnet:open(unix_telnet). +{ok,<0.105.0>} +> ct_telnet:cmd(unix_telnet, "ls ."). +{ok,["ls","file1 ...",...]}
    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_ftp.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_ftp.html 2026-08-21 04:00:19.163293069 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_ftp.html 2026-08-21 04:00:19.163293069 +0000 @@ -554,10 +554,10 @@

    Opens an FTP connection and sends a file to the remote host.

    LocalFile and RemoteFile must be absolute paths.

    If the target host is a "special" node, the FTP address must be specified in the -configuration file as follows:

    {node,[{ftp,IpAddr}]}.

    If the target host is something else, for example, a UNIX host, the -configuration file must also include the username and password (both strings):

    {unix,[{ftp,IpAddr},
    -       {username,Username},
    -       {password,Password}]}.

    See also ct:require/2.

    +configuration file as follows:

    {node,[{ftp,IpAddr}]}.

    If the target host is something else, for example, a UNIX host, the +configuration file must also include the username and password (both strings):

    {unix,[{ftp,IpAddr},
    +       {username,Username},
    +       {password,Password}]}.

    See also ct:require/2.

    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_hooks_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2254)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_hooks_chapter.html 2026-08-21 04:00:19.184293205 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_hooks_chapter.html 2026-08-21 04:00:19.184293205 +0000 @@ -163,12 +163,12 @@ always a combination of a result for the suite/group/test and an updated CTHState.

    To let the test suite continue on executing, return the configuration list that you want the test to use as the result.

    All pre hooks, except pre_end_per_testcase/4, can skip or fail the test by -returning a tuple with skip or fail, and a reason as the result.

    Example:

    pre_init_per_suite(SuiteName, Config, CTHState) ->
    -  case db:connect() of
    -    {error,_Reason} ->
    -      {{fail, "Could not connect to DB"}, CTHState};
    -    {ok, Handle} ->
    -      {[{db_handle, Handle} | Config], CTHState#state{ handle = Handle }}
    +returning a tuple with skip or fail, and a reason as the result.

    Example:

    pre_init_per_suite(SuiteName, Config, CTHState) ->
    +  case db:connect() of
    +    {error,_Reason} ->
    +      {{fail, "Could not connect to DB"}, CTHState};
    +    {ok, Handle} ->
    +      {[{db_handle, Handle} | Config], CTHState#state{ handle = Handle }}
       end.

    Note

    If you use multiple CTHs, the first part of the return tuple is used as input for the next CTH. So in the previous example the next CTH can get {fail,Reason} as the second parameter. If you have many CTHs interacting, do @@ -184,18 +184,18 @@ affect the outcome of the test, return the Return data as it is given to the CTH. You can also modify the test result. By returning the Config list with element tc_status removed, you can recover from a test failure. As in all the -pre hooks, it is also possible to fail/skip the test case in the post hook.

    Example:

    post_end_per_testcase(_Suite, _TC, Config, {'EXIT',{_,_}}, CTHState) ->
    -  case db:check_consistency() of
    +pre hooks, it is also possible to fail/skip the test case in the post hook.

    Example:

    post_end_per_testcase(_Suite, _TC, Config, {'EXIT',{_,_}}, CTHState) ->
    +  case db:check_consistency() of
         true ->
           %% DB is good, pass the test.
    -      {proplists:delete(tc_status, Config), CTHState};
    +      {proplists:delete(tc_status, Config), CTHState};
         false ->
           %% DB is not good, mark as skipped instead of failing
    -      {{skip, "DB is inconsistent!"}, CTHState}
    +      {{skip, "DB is inconsistent!"}, CTHState}
       end;
    -post_end_per_testcase(_Suite, _TC, Config, Return, CTHState) ->
    +post_end_per_testcase(_Suite, _TC, Config, Return, CTHState) ->
       %% Do nothing if tc does not crash.
    -  {Return, CTHState}.

    Note

    Do recover from a testcase failure using CTHs only a last resort. If used + {Return, CTHState}.

    Note

    Do recover from a testcase failure using CTHs only a last resort. If used wrongly, it can be very difficult to determine which tests that pass or fail in a test run.

    Skip and Fail Hooks

    After any post hook has been executed for all installed CTHs, on_tc_fail or @@ -234,80 +234,80 @@ %%% ct_run -suite example_SUITE -pa . -ct_hooks example_cth %%% %%% Note `-pa .`: the hook beam file must be in the code path when installing. --module(example_cth). +-module(example_cth). %% Mandatory Callbacks --export([init/2]). +-export([init/2]). %% Optional Callbacks --export([id/1]). +-export([id/1]). --export([pre_init_per_suite/3]). --export([post_end_per_suite/4]). +-export([pre_init_per_suite/3]). +-export([post_end_per_suite/4]). --export([pre_init_per_testcase/4]). --export([post_end_per_testcase/5]). +-export([pre_init_per_testcase/4]). +-export([post_end_per_testcase/5]). --export([on_tc_skip/4]). +-export([on_tc_skip/4]). --export([terminate/1]). +-export([terminate/1]). %% This hook state is threaded through all the callbacks. --record(state, {filename, total, suite_total, ts, tcs, data, skipped}). +-record(state, {filename, total, suite_total, ts, tcs, data, skipped}). %% This example hook prints its results to a file, see terminate/1. --record(test_run, {total, skipped, suites}). +-record(test_run, {total, skipped, suites}). %% Return a unique id for this CTH. %% Using the filename means the hook can be used with different %% log files to separate timing data within the same test run. %% See Installing a CTH for more information. -id(Opts) -> +id(Opts) -> %% the path is relative to the test run directory - proplists:get_value(filename, Opts, "example_cth.log"). + proplists:get_value(filename, Opts, "example_cth.log"). %% Always called before any other callback function. Use this to initiate %% any common state. -init(Id, _Opts) -> - {ok, #state{filename = Id, total = 0, data = []}}. +init(Id, _Opts) -> + {ok, #state{filename = Id, total = 0, data = []}}. %% Called before init_per_suite is called. -pre_init_per_suite(_Suite,Config,State) -> - {Config, State#state{suite_total = 0, tcs = []}}. +pre_init_per_suite(_Suite,Config,State) -> + {Config, State#state{suite_total = 0, tcs = []}}. %% Called after end_per_suite. -post_end_per_suite(Suite,_Config,Return,State) -> - Data = {suites, Suite, State#state.suite_total, - lists:reverse(State#state.tcs)}, - {Return, State#state{data = [Data | State#state.data], - total = State#state.total + State#state.suite_total}}. +post_end_per_suite(Suite,_Config,Return,State) -> + Data = {suites, Suite, State#state.suite_total, + lists:reverse(State#state.tcs)}, + {Return, State#state{data = [Data | State#state.data], + total = State#state.total + State#state.suite_total}}. %% Called before each init_per_testcase. -pre_init_per_testcase(_Suite,_TC,Config,State) -> - Now = erlang:monotonic_time(microsecond), - {Config, State#state{ts = Now, suite_total = State#state.suite_total + 1}}. +pre_init_per_testcase(_Suite,_TC,Config,State) -> + Now = erlang:monotonic_time(microsecond), + {Config, State#state{ts = Now, suite_total = State#state.suite_total + 1}}. %% Called after each end_per_testcase. -post_end_per_testcase(Suite,TC,_Config,Return,State) -> - Now = erlang:monotonic_time(microsecond), - TCInfo = {testcase, Suite, TC, Return, Now - State#state.ts}, - {Return, State#state{ts = undefined, tcs = [TCInfo | State#state.tcs]}}. +post_end_per_testcase(Suite,TC,_Config,Return,State) -> + Now = erlang:monotonic_time(microsecond), + TCInfo = {testcase, Suite, TC, Return, Now - State#state.ts}, + {Return, State#state{ts = undefined, tcs = [TCInfo | State#state.tcs]}}. %% Called when a test case is skipped by either user action %% or due to an init function failing. -on_tc_skip(_Suite, _TC, _Reason, State) -> - State#state{skipped = State#state.skipped + 1}. +on_tc_skip(_Suite, _TC, _Reason, State) -> + State#state{skipped = State#state.skipped + 1}. %% Called when the scope of the CTH is done. -terminate(State) -> +terminate(State) -> %% use append to avoid data loss if the path is reused - {ok, File} = file:open(State#state.filename, [write, append]), - io:format(File, "~p.~n", [results(State)]), - file:close(File), + {ok, File} = file:open(State#state.filename, [write, append]), + io:format(File, "~p.~n", [results(State)]), + file:close(File), ok. -results(State) -> - #state{skipped = Skipped, data = Data, total = Total} = State, - #test_run{total = Total, skipped = Skipped, suites = lists:reverse(Data)}.

    Built-In CTHs

    Common Test is delivered with some general-purpose CTHs that can be enabled by +results(State) -> + #state{skipped = Skipped, data = Data, total = Total} = State, + #test_run{total = Total, skipped = Skipped, suites = lists:reverse(Data)}.

    Built-In CTHs

    Common Test is delivered with some general-purpose CTHs that can be enabled by the user to provide generic testing functionality. Some of these CTHs are enabled by default when common_test is started to run. They can be disabled by setting enable_builtin_hooks to false on the command line or in the test /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_master.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (804)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_master.html 2026-08-21 04:00:19.206293349 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_master.html 2026-08-21 04:00:19.207293355 +0000 @@ -413,7 +413,7 @@

    Gets a reference to the Common Test master event manager. The reference can be -used to, for example, add a user-specific event handler while tests are running.

    Example:

    gen_event:add_handler(ct_master:get_event_mgr_ref(), my_ev_h, [])
    +used to, for example, add a user-specific event handler while tests are running.

    Example:

    gen_event:add_handler(ct_master:get_event_mgr_ref(), my_ev_h, [])
    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_master_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1303)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_master_chapter.html 2026-08-21 04:00:19.228293492 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_master_chapter.html 2026-08-21 04:00:19.227293485 +0000 @@ -108,7 +108,7 @@ of test specifications. If it is a list, the specifications are handled (and the corresponding tests executed) in sequence. An element in a TestSpecs list can also be list of test specifications. The specifications in such a list are -merged into one combined specification before test execution.

    Example:

    ct_master:run(["ts1","ts2",["ts3","ts4"]])

    Here, the tests specified by "ts1" run first, then the tests specified by "ts2", +merged into one combined specification before test execution.

    Example:

    ct_master:run(["ts1","ts2",["ts3","ts4"]])

    Here, the tests specified by "ts1" run first, then the tests specified by "ts2", and finally the tests specified by both "ts3" and "ts4".

    The InclNodes argument to run/3 is a list of node names. Function run/3 runs the tests in TestSpecs just like run/1, but also takes any test in TestSpecs, which is not explicitly tagged with a particular node name, and @@ -142,32 +142,32 @@ install an event handler).

    Consider the example in section Test Specifications in section Running Tests and Analysing Results, now extended with node information and -intended to be executed by Common Test Master:

    {define, 'Top', "/home/test"}.
    -{define, 'T1', "'Top'/t1"}.
    -{define, 'T2', "'Top'/t2"}.
    -{define, 'T3', "'Top'/t3"}.
    -{define, 'CfgFile', "config.cfg"}.
    -{define, 'Node', ct_node}.
    -
    -{node, node1, 'Node@host_x'}.
    -{node, node2, 'Node@host_y'}.
    -
    -{logdir, master, "'Top'/master_logs"}.
    -{logdir, "'Top'/logs"}.
    -
    -{config, node1, "'T1'/'CfgFile'"}.
    -{config, node2, "'T2'/'CfgFile'"}.
    -{config, "'T3'/'CfgFile'"}.
    -
    -{suites, node1, 'T1', all}.
    -{skip_suites, node1, 'T1', [t1B_SUITE,t1D_SUITE], "Not implemented"}.
    -{skip_cases, node1, 'T1', t1A_SUITE, [test3,test4], "Irrelevant"}.
    -{skip_cases, node1, 'T1', t1C_SUITE, [test1], "Ignore"}.
    +intended to be executed by Common Test Master:

    {define, 'Top', "/home/test"}.
    +{define, 'T1', "'Top'/t1"}.
    +{define, 'T2', "'Top'/t2"}.
    +{define, 'T3', "'Top'/t3"}.
    +{define, 'CfgFile', "config.cfg"}.
    +{define, 'Node', ct_node}.
    +
    +{node, node1, 'Node@host_x'}.
    +{node, node2, 'Node@host_y'}.
    +
    +{logdir, master, "'Top'/master_logs"}.
    +{logdir, "'Top'/logs"}.
    +
    +{config, node1, "'T1'/'CfgFile'"}.
    +{config, node2, "'T2'/'CfgFile'"}.
    +{config, "'T3'/'CfgFile'"}.
    +
    +{suites, node1, 'T1', all}.
    +{skip_suites, node1, 'T1', [t1B_SUITE,t1D_SUITE], "Not implemented"}.
    +{skip_cases, node1, 'T1', t1A_SUITE, [test3,test4], "Irrelevant"}.
    +{skip_cases, node1, 'T1', t1C_SUITE, [test1], "Ignore"}.
     
    -{suites, node2, 'T2', [t2B_SUITE,t2C_SUITE]}.
    -{cases, node2, 'T2', t2A_SUITE, [test4,test1,test7]}.
    +{suites, node2, 'T2', [t2B_SUITE,t2C_SUITE]}.
    +{cases, node2, 'T2', t2A_SUITE, [test4,test1,test7]}.
     
    -{skip_suites, 'T3', all, "Not implemented"}.

    This example specifies the same tests as the original example. But now if +{skip_suites, 'T3', all, "Not implemented"}.

    This example specifies the same tests as the original example. But now if started with a call to ct_master:run(TestSpecName), test t1 is executed on node ct_node@host_x (node1), test t2 on ct_node@host_y (node2) and test t3 on both node1 and node2. Configuration file t1 is only read on @@ -184,13 +184,13 @@ Common Test node in question (typically ct@somehost if started with the ct_run program), is performed. Tests without explicit node association are always performed too, of course.

    Automatic Startup of Test Target Nodes

    Initial actions can be started and performed automatically on test target nodes -using test specification term init.

    Two subterms are supported, node_start and eval.

    Example:

    {node, node1, node1@host1}.
    -{node, node2, node1@host2}.
    -{node, node3, node2@host2}.
    -{node, node4, node1@host3}.
    -{init, node1, [{node_start, [{callback_module, my_slave_callback}]}]}.
    -{init, [node2, node3], {node_start, [{username, "ct_user"}, {password, "ct_password"}]}}.
    -{init, node4, {eval, {module, function, []}}}.

    This test specification declares that node1@host1 is to be started using the +using test specification term init.

    Two subterms are supported, node_start and eval.

    Example:

    {node, node1, node1@host1}.
    +{node, node2, node1@host2}.
    +{node, node3, node2@host2}.
    +{node, node4, node1@host3}.
    +{init, node1, [{node_start, [{callback_module, my_slave_callback}]}]}.
    +{init, [node2, node3], {node_start, [{username, "ct_user"}, {password, "ct_password"}]}}.
    +{init, node4, {eval, {module, function, []}}}.

    This test specification declares that node1@host1 is to be started using the user callback function callback_module:my_slave_callback/0, and nodes node1@host2 and node2@host2 are to be started with the default callback module ct_slave. The specified username and password are used to log on to /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_netconfc.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1594)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_netconfc.html 2026-08-21 04:00:19.266293739 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_netconfc.html 2026-08-21 04:00:19.267293746 +0000 @@ -102,7 +102,7 @@ to the server.

    Alternately, open/1,2 can be used to establish a single session on a dedicated connection. (Or, equivalently, only_open/1,2 followed by hello/1-3.)

    Connect/session options can be specified in a configuration file with entries -like the following.

    {server_id(), [option()]}.

    The server_id/0 or an associated ct:target_name/0 can then be passed to +like the following.

    {server_id(), [option()]}.

    The server_id/0 or an associated ct:target_name/0 can then be passed to the aforementioned functions to use the referenced configuration.

    Signaling

    Protocol operations in the NETCONF protocol are realized as remote procedure calls (RPCs) from client to server and a corresponding reply from server to client. RPCs are sent using like-named functions (eg. @@ -115,8 +115,8 @@ in most cases since a non-response by the server or a missing message-id causes the call to hang indefinitely.

    Logging

    The NETCONF server uses error_logger for logging of NETCONF traffic. A special purpose error handler is implemented in ct_conn_log_h. To use this error -handler, add the cth_conn_log hook in the test suite, for example:

    suite() ->
    -    [{ct_hooks, [{cth_conn_log, [{ct:conn_log_mod(), ct:conn_log_options()}]}]}].

    conn_log_mod() is the name of the Common Test module implementing the +handler, add the cth_conn_log hook in the test suite, for example:

    suite() ->
    +    [{ct_hooks, [{cth_conn_log, [{ct:conn_log_mod(), ct:conn_log_options()}]}]}].

    conn_log_mod() is the name of the Common Test module implementing the connection protocol, for example, ct_netconfc.

    Hook option log_type specifies the type of logging:

    • raw - The sent and received NETCONF data is logged to a separate text file "as is" without any formatting. A link to the file is added to the test case HTML log.

    • pretty - The sent and received NETCONF data is logged to a separate text @@ -127,17 +127,17 @@ option hosts and list the names of the servers/connections to be used in the suite. The connections must be named for this to work, that is, they must be opened with open/2.

      Option hosts has no effect if log_type is set to html or silent.

      The hook options can also be specified in a configuration file with -configuration variable ct_conn_log:

      {ct_conn_log,[{ct:conn_log_mod(), ct:conn_log_options()}]}.

      For example:

      {ct_conn_log,[{ct_netconfc,[{log_type,pretty},
      -                            {hosts,[ct:key_or_name()]}]}]}

      Note

      Hook options specified in a configuration file overwrite the hard-coded hook +configuration variable ct_conn_log:

      {ct_conn_log,[{ct:conn_log_mod(), ct:conn_log_options()}]}.

      For example:

      {ct_conn_log,[{ct_netconfc,[{log_type,pretty},
      +                            {hosts,[ct:key_or_name()]}]}]}

      Note

      Hook options specified in a configuration file overwrite the hard-coded hook options in the test suite.

      Logging Example 1:

      The following ct_hooks statement causes pretty printing of NETCONF traffic to separate logs for the connections named nc_server1 and nc_server2. Any other -connections are logged to default NETCONF log.

      suite() ->
      -   [{ct_hooks, [{cth_conn_log, [{ct_netconfc,[{log_type,pretty}},
      -                                              {hosts,[nc_server1,nc_server2]}]}
      -                               ]}]}].

      Connections must be opened as follows:

      open(nc_server1,[...]),
      -open(nc_server2,[...]).

      Logging Example 2:

      The following configuration file causes raw logging of all NETCONF traffic in to -one single text file:

      {ct_conn_log,[{ct_netconfc,[{log_type,raw}]}]}.

      The ct_hooks statement must look as follows:

      suite() ->
      -    [{ct_hooks, [{cth_conn_log, []}]}].

      The same ct_hooks statement without the configuration file would cause HTML +connections are logged to default NETCONF log.

      suite() ->
      +   [{ct_hooks, [{cth_conn_log, [{ct_netconfc,[{log_type,pretty}},
      +                                              {hosts,[nc_server1,nc_server2]}]}
      +                               ]}]}].

      Connections must be opened as follows:

      open(nc_server1,[...]),
      +open(nc_server2,[...]).

      Logging Example 2:

      The following configuration file causes raw logging of all NETCONF traffic in to +one single text file:

      {ct_conn_log,[{ct_netconfc,[{log_type,raw}]}]}.

      The ct_hooks statement must look as follows:

      suite() ->
      +    [{ct_hooks, [{cth_conn_log, []}]}].

      The same ct_hooks statement without the configuration file would cause HTML logging of all NETCONF connections in to the test case HTML log.

      @@ -2138,8 +2138,8 @@

      Edits configuration data.

      By default only the running target is available, unless the server includes :candidate or :startup in its list of capabilities.

      OptParams can be used for specifying optional parameters (default-operation, test-option, or error-option) to be added to the edit-config request. The -value must be a list containing valid simple XML, for example:

      [{'default-operation', ["none"]},
      - {'error-option', ["rollback-on-error"]}]

      If OptParams is not given, the default value [] is used.

      +value must be a list containing valid simple XML, for example:

      [{'default-operation', ["none"]},
      + {'error-option', ["rollback-on-error"]}]

      If OptParams is not given, the default value [] is used.

    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_property_test.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (850)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_property_test.html 2026-08-21 04:00:19.292293908 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_property_test.html 2026-08-21 04:00:19.292293908 +0000 @@ -100,30 +100,30 @@ directory has a subdirectory property_test, where everything needed for the property tests are collected. The usual Erlang application directory structure is assumed.

    A typical Common Test test suite using ct_property_test is organized as -follows:

    -module(my_prop_test_SUITE).
    --compile(export_all).
    +follows:

    -module(my_prop_test_SUITE).
    +-compile(export_all).
     
    --include_lib("common_test/include/ct.hrl").
    +-include_lib("common_test/include/ct.hrl").
     
    -all() -> [prop_ftp_case].
    +all() -> [prop_ftp_case].
     
    -init_per_suite(Config) ->
    -    ct_property_test:init_per_suite(Config).
    +init_per_suite(Config) ->
    +    ct_property_test:init_per_suite(Config).
     
     %%%---- test case
    -prop_ftp_case(Config) ->
    -    ct_property_test:quickcheck(
    -      ftp_simple_client_server:prop_ftp(),
    +prop_ftp_case(Config) ->
    +    ct_property_test:quickcheck(
    +      ftp_simple_client_server:prop_ftp(),
           Config
    -     ).

    and the the property test module (in this example + ).

    and the the property test module (in this example ftp_simple_client_server.erl) as almost a usual property testing module (More -examples are in the User's Guide):

    -module(ftp_simple_client_server).
    --export([prop_ftp/0...]).
    +examples are in the User's Guide):

    -module(ftp_simple_client_server).
    +-export([prop_ftp/0...]).
     
    --include_lib("common_test/include/ct_property_test.hrl").
    +-include_lib("common_test/include/ct_property_test.hrl").
     
    -prop_ftp() ->
    -    ?FORALL( ....
    +
    prop_ftp() -> + ?FORALL( ....
    @@ -841,7 +841,7 @@ 'EQC', 'PROPER' or 'TRIQ' set, depending on which tool that is first found. This could make parts of the Erlang property tests code to be included or excluded with the macro directives -ifdef(Macro). or -ifndef(Macro)..

    The file(s) in the property_test subdirectory could, or should, include the -ct_property_test include file:

    -include_lib("common_test/include/ct_property_test.hrl").

    This included file will:

    The default StatisticsSpec is:

    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_property_test_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1166)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_property_test_chapter.html 2026-08-21 04:00:19.310294025 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_property_test_chapter.html 2026-08-21 04:00:19.311294032 +0000 @@ -93,51 +93,51 @@ property based testing tools in Common Test test suites.

    Basic knowledge of property based testing is assumed in the following. It is also assumed that at least one of the following property based testing tools is installed and available in the library path:

    What Is Supported?

    The ct_property_test module does the following:

    • Compiles the files with property tests in the subdirectory property_test
    • Tests properties in those files using the first found Property Testing Tool.
    • Saves the results - that is the printouts - in the usual Common Test Log

    Introductory Example

    Assume that we want to test the lists:sort/1 function.

    We need a property to test the function. In normal way, we create -property_test/ct_prop.erl module in the test directory in our application:

    -module(ct_prop).
    --export([prop_sort/0]).
    +property_test/ct_prop.erl module in the test directory in our application:

    -module(ct_prop).
    +-export([prop_sort/0]).
     
     %%% This will include the .hrl file for the installed testing tool:
    --include_lib("common_test/include/ct_property_test.hrl").
    +-include_lib("common_test/include/ct_property_test.hrl").
     
     %%% The property we want to check:
     %%%   For all possibly unsorted lists,
     %%%   the result of lists:sort/1 is sorted.
    -prop_sort() ->
    -    ?FORALL(UnSorted, list(),
    -            is_sorted(lists:sort(UnSorted))
    -           ).
    +prop_sort() ->
    +    ?FORALL(UnSorted, list(),
    +            is_sorted(lists:sort(UnSorted))
    +           ).
     
     %%% Function to check that a list is sorted:
    -is_sorted([]) ->
    +is_sorted([]) ->
         true;
    -is_sorted([_]) ->
    +is_sorted([_]) ->
         true;
    -is_sorted([H1,H2|SortedTail]) when H1 =< H2 ->
    -    is_sorted([H2|SortedTail]);
    -is_sorted(_) ->
    -    false.

    We also need a CommonTest test suite:

    -module(ct_property_test_SUITE).
    --compile(export_all). % Only in tests!
    +is_sorted([H1,H2|SortedTail]) when H1 =< H2 ->
    +    is_sorted([H2|SortedTail]);
    +is_sorted(_) ->
    +    false.

    We also need a CommonTest test suite:

    -module(ct_property_test_SUITE).
    +-compile(export_all). % Only in tests!
     
    --include_lib("common_test/include/ct.hrl").
    +-include_lib("common_test/include/ct.hrl").
     
    -all() -> [prop_sort
    -         ].
    +all() -> [prop_sort
    +         ].
     
     %%% First prepare Config and compile the property tests for the found tool:
    -init_per_suite(Config) ->
    -    ct_property_test:init_per_suite(Config).
    +init_per_suite(Config) ->
    +    ct_property_test:init_per_suite(Config).
     
    -end_per_suite(Config) ->
    +end_per_suite(Config) ->
         Config.
     
     %%%================================================================
     %%% Test suites
     %%%
    -prop_sort(Config) ->
    -    ct_property_test:quickcheck(
    -      ct_prop:prop_sort(),
    +prop_sort(Config) ->
    +    ct_property_test:quickcheck(
    +      ct_prop:prop_sort(),
           Config
    -     ).

    We run it as usual, for example with ct_run in the OS shell:

    ..../test$ ct_run -suite ct_property_test_SUITE
    +     ).

    We run it as usual, for example with ct_run in the OS shell:

    ..../test$ ct_run -suite ct_property_test_SUITE
     .....
     Common Test: Running make in test directories...
     
    @@ -161,13 +161,13 @@
     Testing lib.common_test.ct_property_test_SUITE: TEST COMPLETE, 1 ok, 0 failed of 1 test cases
     
     ....

    A stateful testing example

    Assume a test that generates some parallel stateful commands, and runs 300 -tests:

    prop_parallel(Config) ->
    -    numtests(300,
    -             ?FORALL(Cmds, parallel_commands(?MODULE),
    +tests:

    prop_parallel(Config) ->
    +    numtests(300,
    +             ?FORALL(Cmds, parallel_commands(?MODULE),
                          begin
    -                         RunResult = run_parallel_commands(?MODULE, Cmds),
    -                         ct_property_test:present_result(?MODULE, Cmds, RunResult, Config)
    -                     end)).

    The ct_property_test:present_result/4 is a help function for printing some + RunResult = run_parallel_commands(?MODULE, Cmds), + ct_property_test:present_result(?MODULE, Cmds, RunResult, Config) + end)).

    The ct_property_test:present_result/4 is a help function for printing some statistics in the CommonTest log file.

    Our example test could for example be a simple test of an ftp server, where we perform get, put and delete requests, some of them in parallel. Per default, the result has three sections:

    *** User 2019-12-11 13:28:17.504 ***
    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_run_cmd.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1024))
    --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_run_cmd.html	2026-08-21 04:00:19.328294143 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_run_cmd.html	2026-08-21 04:00:19.328294143 +0000
    @@ -185,10 +185,10 @@
       [-ct_hooks_order test | config]
       [-exit_status ignore_config]

    Refresh HTML Index Files

     ct_run -refresh_logs [-logdir LogDir] [-basic_html]
       [-keep_logs all | NLogs]

    Run Common Test in Interactive Mode

     ct_run -shell
    -  [-config ConfigFile1 ConfigFile2 ... ConfigFileN]
    -  [-userconfig CallbackModule1 ConfigString1 and CallbackModule2
    -   ConfigString2 and .. and CallbackModuleN ConfigStringN]
    -  [-decrypt_key Key] | [-decrypt_file KeyFile]

    Start a Common Test Master Node

     ct_run -ctmaster

    See Also

    For information about the start flags, see section + [-config ConfigFile1 ConfigFile2 ... ConfigFileN] + [-userconfig CallbackModule1 ConfigString1 and CallbackModule2 + ConfigString2 and .. and CallbackModuleN ConfigStringN] + [-decrypt_key Key] | [-decrypt_file KeyFile]

    Start a Common Test Master Node

     ct_run -ctmaster

    See Also

    For information about the start flags, see section Running Tests and Analyzing Results in the User's Guide.

    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_snmp.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2283)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_snmp.html 2026-08-21 04:00:19.358294338 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_snmp.html 2026-08-21 04:00:19.358294338 +0000 @@ -115,15 +115,15 @@ Optional.

  • {agent_target_param_def, [term()] | {data_dir_file, rel_path()}} - Optional.

  • Parameter MgrAgentConfName in the functions is to be a name you allocate in your test suite using a require statement. Example (where -MgrAgentConfName = snmp_mgr_agent):

    suite() -> [{require, snmp_mgr_agent, snmp}].

    or

    ct:require(snmp_mgr_agent, snmp).

    Notice that USM users are needed for SNMPv3 configuration and are not to be +MgrAgentConfName = snmp_mgr_agent):

    suite() -> [{require, snmp_mgr_agent, snmp}].

    or

    ct:require(snmp_mgr_agent, snmp).

    Notice that USM users are needed for SNMPv3 configuration and are not to be confused with users.

    SNMP traps, inform, and report messages are handled by the user callback module. For details, see the SNMP application.

    It is recommended to use the .hrl files created by the Erlang/OTP MIB compiler to define the Object Identifiers (OIDs). For example, to get the Erlang node -name from erlNodeTable in the OTP-MIB:

    Oid = ?erlNodeEntry ++ [?erlNodeName, 1]

    Furthermore, values can be set for SNMP application configuration parameters, +name from erlNodeTable in the OTP-MIB:

    Oid = ?erlNodeEntry ++ [?erlNodeName, 1]

    Furthermore, values can be set for SNMP application configuration parameters, config, server, net_if, and so on (for a list of valid parameters and types, see the User's Guide for the SNMP application). -This is done by defining a configuration data variable on the following form:

    {snmp_app, [{manager, [snmp_app_manager_params()]},
    -            {agent, [snmp_app_agent_params()]}]}.

    A name for the data must be allocated in the suite using require (see the +This is done by defining a configuration data variable on the following form:

    {snmp_app, [{manager, [snmp_app_manager_params()]},
    +            {agent, [snmp_app_agent_params()]}]}.

    A name for the data must be allocated in the suite using require (see the example above). Pass this name as argument SnmpAppConfName to ct_snmp:start/3. ct_snmp specifies default values for some SNMP application configuration parameters (such as {verbosity,trace} for /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_ssh.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_ssh.html 2026-08-21 04:00:19.404294637 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_ssh.html 2026-08-21 04:00:19.404294637 +0000 @@ -98,14 +98,14 @@ that have been started on existing SSH connections (that is, when the original connection type is ssh). Whenever the connection type is sftp, use the SSH connection reference only.

    The following options are valid for specifying an SSH/SFTP connection (that is, -can be used as configuration elements):

    [{ConnType, Addr},
    - {port, Port},
    - {user, UserName}
    - {password, Pwd}
    - {user_dir, String}
    - {public_key_alg, PubKeyAlg}
    - {connect_timeout, Timeout}
    - {key_cb, KeyCallbackMod}]

    ConnType = ssh | sftp.

    For other types, see ssh.

    All time-out parameters in ct_ssh functions are values in milliseconds.

    +can be used as configuration elements):

    [{ConnType, Addr},
    + {port, Port},
    + {user, UserName}
    + {password, Pwd}
    + {user_dir, String}
    + {public_key_alg, PubKeyAlg}
    + {connect_timeout, Timeout}
    + {key_cb, KeyCallbackMod}]

    ConnType = ssh | sftp.

    For other types, see ssh.

    All time-out parameters in ct_ssh functions are values in milliseconds.

    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_telnet.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1874)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_telnet.html 2026-08-21 04:00:19.433294826 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/ct_telnet.html 2026-08-21 04:00:19.434294833 +0000 @@ -101,14 +101,14 @@ true
  • Polling limit (max number of times to poll to get a remaining string terminated) = 0
  • Polling interval (sleep time between polls) = 1 second
  • The TCP_NODELAY option for the telnet socket is disabled (set to false) per default
  • These parameters can be modified by the user with the following configuration -term:

    {telnet_settings, [{connect_timeout,Millisec},
    -                   {command_timeout,Millisec},
    -                   {reconnection_attempts,N},
    -                   {reconnection_interval,Millisec},
    -                   {keep_alive,Bool},
    -                   {poll_limit,N},
    -                   {poll_interval,Millisec},
    -                   {tcp_nodelay,Bool}]}.

    Millisec = timeout(), N = integer()

    Enter the telnet_settings term in a configuration file included in the test +term:

    {telnet_settings, [{connect_timeout,Millisec},
    +                   {command_timeout,Millisec},
    +                   {reconnection_attempts,N},
    +                   {reconnection_interval,Millisec},
    +                   {keep_alive,Bool},
    +                   {poll_limit,N},
    +                   {poll_interval,Millisec},
    +                   {tcp_nodelay,Bool}]}.

    Millisec = timeout(), N = integer()

    Enter the telnet_settings term in a configuration file included in the test and ct_telnet retrieves the information automatically.

    keep_alive can be specified per connection, if necessary. For details, see unix_telnet.

    Logging

    The default logging behavior of ct_telnet is to print information about performed operations, commands, and their corresponding results to the test case @@ -117,8 +117,8 @@ such as expect/3. However, ct_telnet can be configured to use a special purpose event handler, implemented in ct_conn_log_h, for logging all Telnet traffic. To use this handler, install a Common Test hook named -cth_conn_log. Example (using the test suite information function):

    suite() ->
    -    [{ct_hooks, [{cth_conn_log, [{conn_mod(),hook_options()}]}]}].

    conn_mod() is the name of the Common Test module implementing the connection +cth_conn_log. Example (using the test suite information function):

    suite() ->
    +    [{ct_hooks, [{cth_conn_log, [{conn_mod(),hook_options()}]}]}].

    conn_mod() is the name of the Common Test module implementing the connection protocol, that is, ct_telnet.

    The cth_conn_log hook performs unformatted logging of Telnet data to a separate text file. All Telnet communication is captured and printed, including any data sent from the server. The link to this text file is located at the top @@ -135,15 +135,15 @@ disabled, which results with no prefix data. If the value is set to full prefix contains timestamp and additonal information. If the value is set to short prefix includes only human readable timestamp.

    All cth_conn_log hook options described can also be specified in a -configuration file with configuration variable ct_conn_log.

    Example:

    {ct_conn_log, [{ct_telnet,[{log_type,raw},
    -                           {hosts,[key_or_name()]}]}]}

    Note

    Hook options specified in a configuration file overwrite any hard-coded hook +configuration file with configuration variable ct_conn_log.

    Example:

    {ct_conn_log, [{ct_telnet,[{log_type,raw},
    +                           {hosts,[key_or_name()]}]}]}

    Note

    Hook options specified in a configuration file overwrite any hard-coded hook options in the test suite.

    Logging Example:

    The following ct_hooks statement causes printing of Telnet traffic to separate logs for the connections server1 and server2. Traffic for any other -connections is logged in the default Telnet log.

    suite() ->
    -    [{ct_hooks,
    -      [{cth_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}]}].

    As previously explained, this specification can also be provided by an entry -like the following in a configuration file:

    {ct_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}.

    In this case the ct_hooks statement in the test suite can look as follows:

    suite() ->
    -    [{ct_hooks, [{cth_conn_log, []}]}].

    See Also

    unix_telnet

    +connections is logged in the default Telnet log.

    suite() ->
    +    [{ct_hooks,
    +      [{cth_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}]}].

    As previously explained, this specification can also be provided by an entry +like the following in a configuration file:

    {ct_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}.

    In this case the ct_hooks statement in the test suite can look as follows:

    suite() ->
    +    [{ct_hooks, [{cth_conn_log, []}]}].

    See Also

    unix_telnet

    @@ -846,9 +846,9 @@ instead of only one Match. Also HaltReason is returned.

  • sequence - All patterns must be matched in a sequence. A match is not concluded until all patterns are matched. This option can be interrupted by one or more HaltPatterns. MatchList is always returned, that is, a list of -Match instead of only one Match. Also HaltReason is returned.

  • Example 1:

    expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],[sequence,{halt,[{nnn,"NNN"}]}])

    First this tries to match "ABC", and then "XYZ", but if "NNN" appears, the +Match instead of only one Match. Also HaltReason is returned.

    Example 1:

    expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],[sequence,{halt,[{nnn,"NNN"}]}])

    First this tries to match "ABC", and then "XYZ", but if "NNN" appears, the function returns {error,{nnn,["NNN"]}}. If both "ABC" and "XYZ" are -matched, the function returns {ok,[AbcMatch,XyzMatch]}.

    Example 2:

    expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],[{repeat,2},{halt,[{nnn,"NNN"}]}])

    This tries to match "ABC" or "XYZ" twice. If "NNN" appears, the function +matched, the function returns {ok,[AbcMatch,XyzMatch]}.

    Example 2:

    expect(Connection,[{abc,"ABC"},{xyz,"XYZ"}],[{repeat,2},{halt,[{nnn,"NNN"}]}])

    This tries to match "ABC" or "XYZ" twice. If "NNN" appears, the function returns HaltReason = {nnn,["NNN"]}.

    Options repeat and sequence can be combined to match a sequence multiple times.

    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/dependencies_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1170)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/dependencies_chapter.html 2026-08-21 04:00:19.455294969 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/dependencies_chapter.html 2026-08-21 04:00:19.455294969 +0000 @@ -119,65 +119,65 @@ start and stop functionality separately.) The configuration can also be implemented as a common function, maybe grouped with the start function. Finally, the testing of connecting and disconnecting a client can be grouped -into one test case. The resulting suite can look as follows:

    -module(my_server_SUITE).
    --compile(export_all).
    --include_lib("ct.hrl").
    +into one test case. The resulting suite can look as follows:

    -module(my_server_SUITE).
    +-compile(export_all).
    +-include_lib("ct.hrl").
     
     %%% init and end functions...
     
    -suite() -> [{require,my_server_cfg}].
    +suite() -> [{require,my_server_cfg}].
     
    -init_per_testcase(start_and_stop, Config) ->
    +init_per_testcase(start_and_stop, Config) ->
         Config;
     
    -init_per_testcase(config, Config) ->
    -    [{server_pid,start_server()} | Config];
    +init_per_testcase(config, Config) ->
    +    [{server_pid,start_server()} | Config];
     
    -init_per_testcase(_, Config) ->
    -    ServerPid = start_server(),
    -    configure_server(),
    -    [{server_pid,ServerPid} | Config].
    +init_per_testcase(_, Config) ->
    +    ServerPid = start_server(),
    +    configure_server(),
    +    [{server_pid,ServerPid} | Config].
     
    -end_per_testcase(start_and_stop, _) ->
    +end_per_testcase(start_and_stop, _) ->
         ok;
     
    -end_per_testcase(_, Config) ->
    -    ServerPid = proplists:get_value(server_pid, Config),
    -    stop_server(ServerPid).
    +end_per_testcase(_, Config) ->
    +    ServerPid = proplists:get_value(server_pid, Config),
    +    stop_server(ServerPid).
     
     %%% test cases...
     
    -all() -> [start_and_stop, config, connect_and_disconnect].
    +all() -> [start_and_stop, config, connect_and_disconnect].
     
     %% test that starting and stopping works
    -start_and_stop(_) ->
    -    ServerPid = start_server(),
    -    stop_server(ServerPid).
    +start_and_stop(_) ->
    +    ServerPid = start_server(),
    +    stop_server(ServerPid).
     
     %% configuration test
    -config(Config) ->
    -    ServerPid = proplists:get_value(server_pid, Config),
    -    configure_server(ServerPid).
    +config(Config) ->
    +    ServerPid = proplists:get_value(server_pid, Config),
    +    configure_server(ServerPid).
     
     %% test connecting and disconnecting client
    -connect_and_disconnect(Config) ->
    -    ServerPid = proplists:get_value(server_pid, Config),
    -    {ok,SessionId} = my_server:connect(ServerPid),
    -    ok = my_server:disconnect(ServerPid, SessionId).
    +connect_and_disconnect(Config) ->
    +    ServerPid = proplists:get_value(server_pid, Config),
    +    {ok,SessionId} = my_server:connect(ServerPid),
    +    ok = my_server:disconnect(ServerPid, SessionId).
     
     %%% common functions...
     
    -start_server() ->
    -    {ok,ServerPid} = my_server:start(),
    +start_server() ->
    +    {ok,ServerPid} = my_server:start(),
         ServerPid.
     
    -stop_server(ServerPid) ->
    -    ok = my_server:stop(),
    +stop_server(ServerPid) ->
    +    ok = my_server:stop(),
         ok.
     
    -configure_server(ServerPid) ->
    -    ServerCfgData = ct:get_config(my_server_cfg),
    -    ok = my_server:configure(ServerPid, ServerCfgData),
    +configure_server(ServerPid) ->
    +    ServerCfgData = ct:get_config(my_server_cfg),
    +    ok = my_server:configure(ServerPid, ServerCfgData),
         ok.

    Saving Configuration Data

    Sometimes it is impossible, or infeasible, to implement independent test cases. Maybe it is not possible to read the SUT state. Maybe resetting the SUT is impossible and it takes too long time to restart the system. In situations where @@ -199,40 +199,40 @@ data is to be saved by finction end_per_suite and read by function init_per_suite in the suite that follows. When passing data between suites, Saver carries the name -of the test suite.

    Example:

    -module(server_b_SUITE).
    --compile(export_all).
    --include_lib("ct.hrl").
    +of the test suite.

    Example:

    -module(server_b_SUITE).
    +-compile(export_all).
    +-include_lib("ct.hrl").
     
     %%% init and end functions...
     
    -init_per_suite(Config) ->
    +init_per_suite(Config) ->
         %% read config saved by previous test suite
    -    {server_a_SUITE,OldConfig} = proplists:get_value(saved_config, Config),
    +    {server_a_SUITE,OldConfig} = proplists:get_value(saved_config, Config),
         %% extract server identity (comes from server_a_SUITE)
    -    ServerId = proplists:get_value(server_id, OldConfig),
    -    SessionId = connect_to_server(ServerId),
    -    [{ids,{ServerId,SessionId}} | Config].
    +    ServerId = proplists:get_value(server_id, OldConfig),
    +    SessionId = connect_to_server(ServerId),
    +    [{ids,{ServerId,SessionId}} | Config].
     
    -end_per_suite(Config) ->
    +end_per_suite(Config) ->
         %% save config for server_c_SUITE (session_id and server_id)
    -    {save_config,Config}
    +    {save_config,Config}
     
     %%% test cases...
     
    -all() -> [allocate, deallocate].
    +all() -> [allocate, deallocate].
     
    -allocate(Config) ->
    -    {ServerId,SessionId} = proplists:get_value(ids, Config),
    -    {ok,Handle} = allocate_resource(ServerId, SessionId),
    +allocate(Config) ->
    +    {ServerId,SessionId} = proplists:get_value(ids, Config),
    +    {ok,Handle} = allocate_resource(ServerId, SessionId),
         %% save handle for deallocation test
    -    NewConfig = [{handle,Handle}],
    -    {save_config,NewConfig}.
    +    NewConfig = [{handle,Handle}],
    +    {save_config,NewConfig}.
     
    -deallocate(Config) ->
    -    {ServerId,SessionId} = proplists:get_value(ids, Config),
    -    {allocate,OldConfig} = proplists:get_value(saved_config, Config),
    -    Handle = proplists:get_value(handle, OldConfig),
    -    ok = deallocate_resource(ServerId, SessionId, Handle).

    To save Config data from a test case that is to be skipped, return tuple +deallocate(Config) -> + {ServerId,SessionId} = proplists:get_value(ids, Config), + {allocate,OldConfig} = proplists:get_value(saved_config, Config), + Handle = proplists:get_value(handle, OldConfig), + ok = deallocate_resource(ServerId, SessionId, Handle).

    To save Config data from a test case that is to be skipped, return tuple {skip_and_save,Reason,ConfigList}.

    The result is that the test case is skipped with Reason printed to the log file (as described earlier) and ConfigList is saved for the next test case. ConfigList can be read using proplists:get_value(saved_config, Config), as @@ -246,22 +246,22 @@ property. Test case groups are defined through function groups/0 in the test suite (for details, see section Test Case Groups.

    For example, to ensure that if allocate in server_b_SUITE crashes, -deallocate is skipped, the following sequence can be defined:

    groups() -> [{alloc_and_dealloc, [sequence], [alloc,dealloc]}].

    Assume that the suite contains the test case get_resource_status that is -independent of the other two cases, then function all can look as follows:

    all() -> [{group,alloc_and_dealloc}, get_resource_status].

    If alloc succeeds, dealloc is also executed. If alloc fails however, +deallocate is skipped, the following sequence can be defined:

    groups() -> [{alloc_and_dealloc, [sequence], [alloc,dealloc]}].

    Assume that the suite contains the test case get_resource_status that is +independent of the other two cases, then function all can look as follows:

    all() -> [{group,alloc_and_dealloc}, get_resource_status].

    If alloc succeeds, dealloc is also executed. If alloc fails however, dealloc is not executed but marked as SKIPPED in the HTML log. get_resource_status runs no matter what happens to the alloc_and_dealloc cases.

    Test cases in a sequence are executed in order until all succeed or one fails. If one fails, all following cases in the sequence are skipped. The cases in the sequence that have succeeded up to that point are reported as successful in the -log. Any number of sequences can be specified.

    Example:

    groups() -> [{scenarioA, [sequence], [testA1, testA2]},
    -             {scenarioB, [sequence], [testB1, testB2, testB3]}].
    +log. Any number of sequences can be specified.

    Example:

    groups() -> [{scenarioA, [sequence], [testA1, testA2]},
    +             {scenarioB, [sequence], [testB1, testB2, testB3]}].
     
    -all() -> [test1,
    +all() -> [test1,
               test2,
    -          {group,scenarioA},
    +          {group,scenarioA},
               test3,
    -          {group,scenarioB},
    -          test4].

    A sequence group can have subgroups. Such subgroups can have any property, that + {group,scenarioB}, + test4].

    A sequence group can have subgroups. Such subgroups can have any property, that is, they are not required to also be sequences. If you want the status of the subgroup to affect the sequence on the level above, return {return_group_result,Status} from /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/event_handler_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1529)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/event_handler_chapter.html 2026-08-21 04:00:19.475295100 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/event_handler_chapter.html 2026-08-21 04:00:19.476295106 +0000 @@ -120,12 +120,12 @@ ct_run -event_handler_init instead of -event_handler.

    Note

    All event handler modules must have gen_event behavior. These modules must be precompiled and their locations must be added explicitly to the Erlang code server search path (as in the previous example).

    An event_handler tuple in argument Opts has the following definition (see -ct:run_test/1):

    {event_handler,EventHandlers}
    +ct:run_test/1):

    {event_handler,EventHandlers}
     
    -EventHandlers = EH | [EH]
    -EH = atom() | {atom(),InitArgs} | {[atom()],InitArgs}
    -InitArgs = [term()]

    In the following example, two event handlers for the my_SUITE test are -installed:

    1> ct:run_test([{suite,"test/my_SUITE"},{event_handler,[my_evh1,{my_evh2,[node()]}]}]).

    Event handler my_evh1 is started with [] as argument to the init function. +EventHandlers = EH | [EH] +EH = atom() | {atom(),InitArgs} | {[atom()],InitArgs} +InitArgs = [term()]

    In the following example, two event handlers for the my_SUITE test are +installed:

    1> ct:run_test([{suite,"test/my_SUITE"},{event_handler,[my_evh1,{my_evh2,[node()]}]}]).

    Event handler my_evh1 is started with [] as argument to the init function. Event handler my_evh2 is started with the name of the current node in the init argument list.

    Event handlers can also be plugged in using one of the following test specification terms:

    • {event_handler, EventHandlers}
    • {event_handler, EventHandlers, InitArgs}
    • {event_handler, NodeRefs, EventHandlers}
    • {event_handler, NodeRefs, EventHandlers, InitArgs}

    EventHandlers is a list of module names. Before a test session starts, the /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/example_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/example_chapter.html 2026-08-21 04:00:19.497295243 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/example_chapter.html 2026-08-21 04:00:19.497295243 +0000 @@ -89,19 +89,19 @@ -

    Test Suite Example

    The following example test suite shows some tests of a database server:

    -module(db_data_type_SUITE).
    +

    Test Suite Example

    The following example test suite shows some tests of a database server:

    -module(db_data_type_SUITE).
     
    --include_lib("common_test/include/ct.hrl").
    +-include_lib("common_test/include/ct.hrl").
     
     %% Test server callbacks
    --export([suite/0, all/0,
    +-export([suite/0, all/0,
              init_per_suite/1, end_per_suite/1,
    -         init_per_testcase/2, end_per_testcase/2]).
    +         init_per_testcase/2, end_per_testcase/2]).
     
     %% Test cases
    --export([string/1, integer/1]).
    +-export([string/1, integer/1]).
     
    --define(CONNECT_STR, "DSN=sqlserver;UID=alladin;PWD=sesame").
    +-define(CONNECT_STR, "DSN=sqlserver;UID=alladin;PWD=sesame").
     
     %%--------------------------------------------------------------------
     %% COMMON TEST CALLBACK FUNCTIONS
    @@ -116,8 +116,8 @@
     %% Description: Returns list of tuples to set default properties
     %%              for the suite.
     %%--------------------------------------------------------------------
    -suite() ->
    -    [{timetrap,{minutes,1}}].
    +suite() ->
    +    [{timetrap,{minutes,1}}].
     
     %%--------------------------------------------------------------------
     %% Function: init_per_suite(Config0) -> Config1
    @@ -127,10 +127,10 @@
     %%
     %% Description: Initialization before the suite.
     %%--------------------------------------------------------------------
    -init_per_suite(Config) ->
    -    {ok, Ref} = db:connect(?CONNECT_STR, []),
    -    TableName = db_lib:unique_table_name(),
    -    [{con_ref, Ref },{table_name, TableName}| Config].
    +init_per_suite(Config) ->
    +    {ok, Ref} = db:connect(?CONNECT_STR, []),
    +    TableName = db_lib:unique_table_name(),
    +    [{con_ref, Ref },{table_name, TableName}| Config].
     
     %%--------------------------------------------------------------------
     %% Function: end_per_suite(Config) -> term()
    @@ -140,9 +140,9 @@
     %%
     %% Description: Cleanup after the suite.
     %%--------------------------------------------------------------------
    -end_per_suite(Config) ->
    -    Ref = proplists:get_value(con_ref, Config),
    -    db:disconnect(Ref),
    +end_per_suite(Config) ->
    +    Ref = proplists:get_value(con_ref, Config),
    +    db:disconnect(Ref),
         ok.
     
     %%--------------------------------------------------------------------
    @@ -155,10 +155,10 @@
     %%
     %% Description: Initialization before each test case.
     %%--------------------------------------------------------------------
    -init_per_testcase(Case, Config) ->
    -    Ref = proplists:get_value(con_ref, Config),
    -    TableName = proplists:get_value(table_name, Config),
    -    ok = db:create_table(Ref, TableName, table_type(Case)),
    +init_per_testcase(Case, Config) ->
    +    Ref = proplists:get_value(con_ref, Config),
    +    TableName = proplists:get_value(table_name, Config),
    +    ok = db:create_table(Ref, TableName, table_type(Case)),
         Config.
     
     %%--------------------------------------------------------------------
    @@ -171,10 +171,10 @@
     %%
     %% Description: Cleanup after each test case.
     %%--------------------------------------------------------------------
    -end_per_testcase(_Case, Config) ->
    -    Ref = proplists:get_value(con_ref, Config),
    -    TableName = proplists:get_value(table_name, Config),
    -    ok = db:delete_table(Ref, TableName),
    +end_per_testcase(_Case, Config) ->
    +    Ref = proplists:get_value(con_ref, Config),
    +    TableName = proplists:get_value(table_name, Config),
    +    ok = db:delete_table(Ref, TableName),
         ok.
     
     %%--------------------------------------------------------------------
    @@ -189,28 +189,28 @@
     %% Description: Returns the list of groups and test cases that
     %%              are to be executed.
     %%--------------------------------------------------------------------
    -all() ->
    -    [string, integer].
    +all() ->
    +    [string, integer].
     
     
     %%--------------------------------------------------------------------
     %% TEST CASES
     %%--------------------------------------------------------------------
     
    -string(Config) ->
    -    insert_and_lookup(dummy_key, "Dummy string", Config).
    +string(Config) ->
    +    insert_and_lookup(dummy_key, "Dummy string", Config).
     
    -integer(Config) ->
    -    insert_and_lookup(dummy_key, 42, Config).
    +integer(Config) ->
    +    insert_and_lookup(dummy_key, 42, Config).
     
     
    -insert_and_lookup(Key, Value, Config) ->
    -    Ref = proplists:get_value(con_ref, Config),
    -    TableName = proplists:get_value(table_name, Config),
    -    ok = db:insert(Ref, TableName, Key, Value),
    -    [Value] = db:lookup(Ref, TableName, Key),
    -    ok = db:delete(Ref, TableName, Key),
    -    [] = db:lookup(Ref, TableName, Key),
    +insert_and_lookup(Key, Value, Config) ->
    +    Ref = proplists:get_value(con_ref, Config),
    +    TableName = proplists:get_value(table_name, Config),
    +    ok = db:insert(Ref, TableName, Key, Value),
    +    [Value] = db:lookup(Ref, TableName, Key),
    +    ok = db:delete(Ref, TableName, Key),
    +    [] = db:lookup(Ref, TableName, Key),
         ok.

    Test Suite Templates

    The Erlang mode for the Emacs editor includes two Common Test test suite templates, one with extensive information in the function headers, and one with minimal information. A test suite template provides a quick start for @@ -222,12 +222,12 @@ %%% %%% Created : %%%------------------------------------------------------------------- --module(example_SUITE). +-module(example_SUITE). %% Note: This directive should only be used in test suites. --compile(export_all). +-compile(export_all). --include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/include/ct.hrl"). %%-------------------------------------------------------------------- %% COMMON TEST CALLBACK FUNCTIONS @@ -245,8 +245,8 @@ %% Note: The suite/0 function is only meant to be used to return %% default data values, not perform any other operations. %%-------------------------------------------------------------------- -suite() -> - [{timetrap,{minutes,10}}]. +suite() -> + [{timetrap,{minutes,10}}]. %%-------------------------------------------------------------------- %% Function: init_per_suite(Config0) -> @@ -262,7 +262,7 @@ %% 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) -> +init_per_suite(Config) -> Config. %%-------------------------------------------------------------------- @@ -273,7 +273,7 @@ %% %% Description: Cleanup after the suite. %%-------------------------------------------------------------------- -end_per_suite(_Config) -> +end_per_suite(_Config) -> ok. %%-------------------------------------------------------------------- @@ -289,7 +289,7 @@ %% %% Description: Initialization before each test case group. %%-------------------------------------------------------------------- -init_per_group(_GroupName, Config) -> +init_per_group(_GroupName, Config) -> Config. %%-------------------------------------------------------------------- @@ -303,7 +303,7 @@ %% %% Description: Cleanup after each test case group. %%-------------------------------------------------------------------- -end_per_group(_GroupName, _Config) -> +end_per_group(_GroupName, _Config) -> ok. /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/getting_started_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1623)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/getting_started_chapter.html 2026-08-21 04:00:19.520295392 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/getting_started_chapter.html 2026-08-21 04:00:19.517295373 +0000 @@ -115,47 +115,47 @@ the test suite module implements callback functions (mandatory or optional) for various purposes, for example:

    • Init/end configuration function for the test suite
    • Init/end configuration function for a test case
    • Init/end configuration function for a test case group
    • Test cases

    The configuration functions are optional. The following example is a test suite without configuration functions, including one simple test case, to check that -module mymod exists (that is, can be successfully loaded by the code server):

    -module(my1st_SUITE).
    --compile(export_all).
    +module mymod exists (that is, can be successfully loaded by the code server):

    -module(my1st_SUITE).
    +-compile(export_all).
     
    -all() ->
    -    [mod_exists].
    +all() ->
    +    [mod_exists].
     
    -mod_exists(_) ->
    -    {module,mymod} = code:load_file(mymod).

    If the operation fails, a bad match error occurs that terminates the test case.

    A Test Suite with Configuration Functions

    If you need to perform configuration operations to run your test, you can +mod_exists(_) -> + {module,mymod} = code:load_file(mymod).

    If the operation fails, a bad match error occurs that terminates the test case.

    A Test Suite with Configuration Functions

    If you need to perform configuration operations to run your test, you can implement configuration functions in your suite. The result from a configuration function is configuration data, or Config. This is a list of key-value tuples that get passed from the configuration function to the test cases (possibly through configuration functions on "lower level"). The data flow looks as follows:

    Configuration Data Flow in a Suite

    The following example shows a test suite that uses configuration functions to open and close a log file for the test cases (an operation that is unnecessary -and irrelevant to perform by each test case):

    -module(check_log_SUITE).
    --export([all/0, init_per_suite/1, end_per_suite/1]).
    --export([check_restart_result/1, check_no_errors/1]).
    +and irrelevant to perform by each test case):

    -module(check_log_SUITE).
    +-export([all/0, init_per_suite/1, end_per_suite/1]).
    +-export([check_restart_result/1, check_no_errors/1]).
     
    --define(value(Key,Config), proplists:get_value(Key,Config)).
    +-define(value(Key,Config), proplists:get_value(Key,Config)).
     
    -all() -> [check_restart_result, check_no_errors].
    +all() -> [check_restart_result, check_no_errors].
     
    -init_per_suite(InitConfigData) ->
    -    [{logref,open_log()} | InitConfigData].
    +init_per_suite(InitConfigData) ->
    +    [{logref,open_log()} | InitConfigData].
     
    -end_per_suite(ConfigData) ->
    -    close_log(?value(logref, ConfigData)).
    +end_per_suite(ConfigData) ->
    +    close_log(?value(logref, ConfigData)).
     
    -check_restart_result(ConfigData) ->
    -    TestData = read_log(restart, ?value(logref, ConfigData)),
    -    {match,_Line} = search_for("restart successful", TestData).
    +check_restart_result(ConfigData) ->
    +    TestData = read_log(restart, ?value(logref, ConfigData)),
    +    {match,_Line} = search_for("restart successful", TestData).
     
    -check_no_errors(ConfigData) ->
    -    TestData = read_log(all, ?value(logref, ConfigData)),
    -    case search_for("error", TestData) of
    -        {match,Line} -> ct:fail({error_found_in_log,Line});
    +check_no_errors(ConfigData) ->
    +    TestData = read_log(all, ?value(logref, ConfigData)),
    +    case search_for("error", TestData) of
    +        {match,Line} -> ct:fail({error_found_in_log,Line});
             nomatch -> ok
         end.

    The test cases verify, by parsing a log file, that our SUT has performed a successful restart and that no unexpected errors are printed.

    To execute the test cases in the recent test suite, type the following on the UNIX/Linux command line (assuming that the suite module is in the current -working directory):

    $ ct_run -dir .

    or:

    $ ct_run -suite check_log_SUITE

    To use the Erlang shell to run our test, you can evaluate the following call:

    1> ct:run_test([{dir, "."}]).

    or:

    1> ct:run_test([{suite, "check_log_SUITE"}]).

    The result from running the test is printed in log files in HTML format (stored +working directory):

    $ ct_run -dir .

    or:

    $ ct_run -suite check_log_SUITE

    To use the Erlang shell to run our test, you can evaluate the following call:

    1> ct:run_test([{dir, "."}]).

    or:

    1> ct:run_test([{suite, "check_log_SUITE"}]).

    The result from running the test is printed in log files in HTML format (stored in unique log directories on a different level). The following illustration shows the log file structure:

    HTML Log File Structure

    Questions and Answers

    Here follows some questions that you might have after reading this section with corresponding tips and links to the answers:

    • Question: "How and where can I specify variable data for my tests that must /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/run_test_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (3302)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/run_test_chapter.html 2026-08-21 04:00:19.557295633 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/run_test_chapter.html 2026-08-21 04:00:19.558295640 +0000 @@ -208,7 +208,7 @@ which instead is printed to tty at the end of the test run.

      Note

      To use the functions ct:break/1,2 and ct:continue/0,1, release_shell must be set to true.

      For details, see ct:run_test/1 manual page.

      Test Case Group Execution

      With the ct_run flag, or ct:run_test/1 option group, one or more test case groups can be specified, optionally in combination with specific test cases. The -syntax for specifying groups on the command line is as follows:

      $ ct_run -group <group_names_or_paths> [-case <cases>]

      The syntax in the Erlang shell is as follows:

      1> ct:run_test([{group,GroupsNamesOrPaths}, {case,Cases}]).

      Parameter group_names_or_paths specifies one or more group names and/or one or +syntax for specifying groups on the command line is as follows:

      $ ct_run -group <group_names_or_paths> [-case <cases>]

      The syntax in the Erlang shell is as follows:

      1> ct:run_test([{group,GroupsNamesOrPaths}, {case,Cases}]).

      Parameter group_names_or_paths specifies one or more group names and/or one or more group paths. At startup, Common Test searches for matching groups in the group definitions tree (that is, the list returned from Suite:groups/0; for details, see section Test Case Groups.

      Given a group name, say g, Common Test searches for all paths leading to @@ -240,30 +240,30 @@ paths if an incomplete group path is specified.

      Note

      Group names and group paths can be combined with parameter group_names_or_paths. Each element is treated as an individual specification in combination with parameter cases. The following examples illustrates -this.

      Examples:

      -module(x_SUITE).
      +this.

      Examples:

      -module(x_SUITE).
       ...
       %% The group definitions:
      -groups() ->
      -  [{top1,[],[tc11,tc12,
      -             {sub11,[],[tc12,tc13]},
      -             {sub12,[],[tc14,tc15,
      -       		 {sub121,[],[tc12,tc16]}]}]},
      -
      -   {top2,[],[{group,sub21},{group,sub22}]},
      -   {sub21,[],[tc21,{group,sub2X2}]},
      -   {sub22,[],[{group,sub221},tc21,tc22,{group,sub2X2}]},
      -   {sub221,[],[tc21,tc23]},
      -   {sub2X2,[],[tc21,tc24]}].

      The following executes two tests, one for all cases and all subgroups under -top1, and one for all under top2:

      $ ct_run -suite "x_SUITE" -group all
      1> ct:run_test([{suite,"x_SUITE"}, {group,all}]).

      Using -group top1 top2, or {group,[top1,top2]} gives the same result.

      The following executes one test for all cases and subgroups under top1:

      $ ct_run -suite "x_SUITE" -group top1
      1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}]).

      The following runs a test executing tc12 in top1 and any subgroup under -top1 where it can be found (sub11 and sub121):

      $ ct_run -suite "x_SUITE" -group top1 -case tc12
      1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}, {testcase,[tc12]}]).

      The following executes tc12 only in group top1:

      $ ct_run -suite "x_SUITE" -group [top1] -case tc12
      1> ct:run_test([{suite,"x_SUITE"}, {group,[[top1]]}, {testcase,[tc12]}]).

      The following searches top1 and all its subgroups for tc16 resulting in that -this test case executes in group sub121:

      $ ct_run -suite "x_SUITE" -group top1 -case tc16
      1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}, {testcase,[tc16]}]).

      Using the specific path -group [sub121] or {group,[[sub121]]} gives the same +groups() -> + [{top1,[],[tc11,tc12, + {sub11,[],[tc12,tc13]}, + {sub12,[],[tc14,tc15, + {sub121,[],[tc12,tc16]}]}]}, + + {top2,[],[{group,sub21},{group,sub22}]}, + {sub21,[],[tc21,{group,sub2X2}]}, + {sub22,[],[{group,sub221},tc21,tc22,{group,sub2X2}]}, + {sub221,[],[tc21,tc23]}, + {sub2X2,[],[tc21,tc24]}].

      The following executes two tests, one for all cases and all subgroups under +top1, and one for all under top2:

      $ ct_run -suite "x_SUITE" -group all
      1> ct:run_test([{suite,"x_SUITE"}, {group,all}]).

      Using -group top1 top2, or {group,[top1,top2]} gives the same result.

      The following executes one test for all cases and subgroups under top1:

      $ ct_run -suite "x_SUITE" -group top1
      1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}]).

      The following runs a test executing tc12 in top1 and any subgroup under +top1 where it can be found (sub11 and sub121):

      $ ct_run -suite "x_SUITE" -group top1 -case tc12
      1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}, {testcase,[tc12]}]).

      The following executes tc12 only in group top1:

      $ ct_run -suite "x_SUITE" -group [top1] -case tc12
      1> ct:run_test([{suite,"x_SUITE"}, {group,[[top1]]}, {testcase,[tc12]}]).

      The following searches top1 and all its subgroups for tc16 resulting in that +this test case executes in group sub121:

      $ ct_run -suite "x_SUITE" -group top1 -case tc16
      1> ct:run_test([{suite,"x_SUITE"}, {group,[top1]}, {testcase,[tc16]}]).

      Using the specific path -group [sub121] or {group,[[sub121]]} gives the same result in this example.

      The following executes two tests, one including all cases and subgroups under -sub12, and one with only the test cases in sub12:

      $ ct_run -suite "x_SUITE" -group sub12 [sub12]
      1> ct:run_test([{suite,"x_SUITE"}, {group,[sub12,[sub12]]}]).

      In the following example, Common Test finds and executes two tests, one for +sub12, and one with only the test cases in sub12:

      $ ct_run -suite "x_SUITE" -group sub12 [sub12]
      1> ct:run_test([{suite,"x_SUITE"}, {group,[sub12,[sub12]]}]).

      In the following example, Common Test finds and executes two tests, one for the path from top2 to sub2X2 through sub21, and one from top2 to -sub2X2 through sub22:

      $ ct_run -suite "x_SUITE" -group sub2X2
      1> ct:run_test([{suite,"x_SUITE"}, {group,[sub2X2]}]).

      In the following example, by specifying the unique path +sub2X2 through sub22:

      $ ct_run -suite "x_SUITE" -group sub2X2
      1> ct:run_test([{suite,"x_SUITE"}, {group,[sub2X2]}]).

      In the following example, by specifying the unique path top2 -> sub21 -> sub2X2, only one test is executed. The second possible path, -from top2 to sub2X2 (from the former example) is discarded:

      $ ct_run -suite "x_SUITE" -group [sub21,sub2X2]
      1> ct:run_test([{suite,"x_SUITE"}, {group,[[sub21,sub2X2]]}]).

      The following executes only the test cases for sub22 and in reverse order -compared to the group definition:

      $ ct_run -suite "x_SUITE" -group [sub22] -case tc22 tc21
      1> ct:run_test([{suite,"x_SUITE"}, {group,[[sub22]]}, {testcase,[tc22,tc21]}]).

      If a test case belonging to a group (according to the group definition) is +from top2 to sub2X2 (from the former example) is discarded:

      $ ct_run -suite "x_SUITE" -group [sub21,sub2X2]
      1> ct:run_test([{suite,"x_SUITE"}, {group,[[sub21,sub2X2]]}]).

      The following executes only the test cases for sub22 and in reverse order +compared to the group definition:

      $ ct_run -suite "x_SUITE" -group [sub22] -case tc22 tc21
      1> ct:run_test([{suite,"x_SUITE"}, {group,[[sub22]]}, {testcase,[tc22,tc21]}]).

      If a test case belonging to a group (according to the group definition) is executed without a group specification, that is, simply by (using the command line):

      $ ct_run -suite "my_SUITE" -case my_tc

      or (using the Erlang shell):

      1> ct:run_test([{suite,"my_SUITE"}, {testcase,my_tc}]).

      then Common Test ignores the group definition and executes the test case in the scope of the test suite only (no group configuration functions are called).

      The group specification feature, as presented in this section, can also be used @@ -285,12 +285,12 @@ configuration data with ct:require/1,2. This is equivalent to a require statement in the Test Suite Information Function or in the -Test Case Information Function.

      Example:

      1> ct:require(unix_telnet, unix).
      +Test Case Information Function.

      Example:

      1> ct:require(unix_telnet, unix).
       ok
      -2> ct_telnet:open(unix_telnet).
      -{ok,<0.105.0>}
      -4> ct_telnet:cmd(unix_telnet, "ls .").
      -{ok,["ls .","file1  ...",...]}

      Everything that Common Test normally prints in the test case logs, are in the +2> ct_telnet:open(unix_telnet). +{ok,<0.105.0>} +4> ct_telnet:cmd(unix_telnet, "ls ."). +{ok,["ls .","file1 ...",...]}

      Everything that Common Test normally prints in the test case logs, are in the interactive mode written to a log named ctlog.html in directory ct_run.<timestamp>. A link to this file is available in the file named last_interactive.html in the directory from which you execute ct_run. @@ -347,8 +347,8 @@ included specification can either be joined with the source specification or used to produce a separate test run (as with start flag/option join_specs above).

      Example:

      %% In specification file "a.spec"
      -{specs, join, ["b.spec", "c.spec"]}.
      -{specs, separate, ["d.spec", "e.spec"]}.
      +{specs, join, ["b.spec", "c.spec"]}.
      +{specs, separate, ["d.spec", "e.spec"]}.
       %% Config and test terms follow
       ...

      In this example, the test terms defined in files "b.spec" and "c.spec" are joined with the terms in source specification "a.spec" (if any). The inclusion @@ -398,154 +398,154 @@ available start flags (as most flags have a corresponding configuration term)

    • Logging (for terms verbosity, stylesheet, basic_html and esc_chars)
    • External Configuration Data (for terms config and userconfig)
    • Event Handling (for the -event_handler term)
    • Common Test Hooks (for term ct_hooks)

    Configuration terms:

    {merge_tests, Bool}.
    +event_handler term)
  • Common Test Hooks (for term ct_hooks)
  • Configuration terms:

    {merge_tests, Bool}.
     
    -{define, Constant, Value}.
    +{define, Constant, Value}.
     
    -{specs, InclSpecsOption, TestSpecs}.
    +{specs, InclSpecsOption, TestSpecs}.
     
    -{node, NodeAlias, Node}.
    +{node, NodeAlias, Node}.
     
    -{init, InitOptions}.
    -{init, [NodeAlias], InitOptions}.
    +{init, InitOptions}.
    +{init, [NodeAlias], InitOptions}.
     
    -{label, Label}.
    -{label, NodeRefs, Label}.
    +{label, Label}.
    +{label, NodeRefs, Label}.
     
    -{verbosity, VerbosityLevels}.
    -{verbosity, NodeRefs, VerbosityLevels}.
    +{verbosity, VerbosityLevels}.
    +{verbosity, NodeRefs, VerbosityLevels}.
     
    -{stylesheet, CSSFile}.
    -{stylesheet, NodeRefs, CSSFile}.
    +{stylesheet, CSSFile}.
    +{stylesheet, NodeRefs, CSSFile}.
     
    -{silent_connections, ConnTypes}.
    -{silent_connections, NodeRefs, ConnTypes}.
    +{silent_connections, ConnTypes}.
    +{silent_connections, NodeRefs, ConnTypes}.
     
    -{multiply_timetraps, N}.
    -{multiply_timetraps, NodeRefs, N}.
    +{multiply_timetraps, N}.
    +{multiply_timetraps, NodeRefs, N}.
     
    -{scale_timetraps, Bool}.
    -{scale_timetraps, NodeRefs, Bool}.
    +{scale_timetraps, Bool}.
    +{scale_timetraps, NodeRefs, Bool}.
     
    -{cover, CoverSpecFile}.
    -{cover, NodeRefs, CoverSpecFile}.
    +{cover, CoverSpecFile}.
    +{cover, NodeRefs, CoverSpecFile}.
     
    -{cover_stop, Bool}.
    -{cover_stop, NodeRefs, Bool}.
    +{cover_stop, Bool}.
    +{cover_stop, NodeRefs, Bool}.
     
    -{include, IncludeDirs}.
    -{include, NodeRefs, IncludeDirs}.
    +{include, IncludeDirs}.
    +{include, NodeRefs, IncludeDirs}.
     
    -{auto_compile, Bool},
    -{auto_compile, NodeRefs, Bool},
    +{auto_compile, Bool},
    +{auto_compile, NodeRefs, Bool},
     
    -{abort_if_missing_suites, Bool},
    -{abort_if_missing_suites, NodeRefs, Bool},
    +{abort_if_missing_suites, Bool},
    +{abort_if_missing_suites, NodeRefs, Bool},
     
    -{config, ConfigFiles}.
    -{config, ConfigDir, ConfigBaseNames}.
    -{config, NodeRefs, ConfigFiles}.
    -{config, NodeRefs, ConfigDir, ConfigBaseNames}.
    +{config, ConfigFiles}.
    +{config, ConfigDir, ConfigBaseNames}.
    +{config, NodeRefs, ConfigFiles}.
    +{config, NodeRefs, ConfigDir, ConfigBaseNames}.
     
    -{userconfig, {CallbackModule, ConfigStrings}}.
    -{userconfig, NodeRefs, {CallbackModule, ConfigStrings}}.
    +{userconfig, {CallbackModule, ConfigStrings}}.
    +{userconfig, NodeRefs, {CallbackModule, ConfigStrings}}.
     
    -{logdir, LogDir}.
    -{logdir, NodeRefs, LogDir}.
    +{logdir, LogDir}.
    +{logdir, NodeRefs, LogDir}.
     
    -{logopts, LogOpts}.
    -{logopts, NodeRefs, LogOpts}.
    +{logopts, LogOpts}.
    +{logopts, NodeRefs, LogOpts}.
     
    -{create_priv_dir, PrivDirOption}.
    -{create_priv_dir, NodeRefs, PrivDirOption}.
    +{create_priv_dir, PrivDirOption}.
    +{create_priv_dir, NodeRefs, PrivDirOption}.
     
    -{event_handler, EventHandlers}.
    -{event_handler, NodeRefs, EventHandlers}.
    -{event_handler, EventHandlers, InitArgs}.
    -{event_handler, NodeRefs, EventHandlers, InitArgs}.
    +{event_handler, EventHandlers}.
    /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/unix_telnet.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1667))
    --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/unix_telnet.html	2026-08-21 04:00:19.577295764 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/unix_telnet.html	2026-08-21 04:00:19.577295764 +0000
    @@ -94,14 +94,14 @@
     
         

    Callback module for ct_telnet, for connecting to a Telnet server on a UNIX -host.

    It requires the following entry in the configuration file:

    {unix,[{telnet,HostNameOrIpAddress},
    -       {port,PortNum},                 % optional
    -       {username,UserName},
    -       {password,Password},
    -       {keep_alive,Bool}]}.            % optional

    To communicate through Telnet to the host specified by HostNameOrIpAddress, +host.

    It requires the following entry in the configuration file:

    {unix,[{telnet,HostNameOrIpAddress},
    +       {port,PortNum},                 % optional
    +       {username,UserName},
    +       {password,Password},
    +       {keep_alive,Bool}]}.            % optional

    To communicate through Telnet to the host specified by HostNameOrIpAddress, use the interface functions in ct_telnet, for example, open(Name) and cmd(Name,Cmd).

    Name is the name you allocated to the Unix host in your require statement, -for example:

    suite() -> [{require,Name,{unix,[telnet]}}].

    or

    ct:require(Name,{unix,[telnet]}).

    The "keep alive" activity (that is, that Common Test sends NOP to the server +for example:

    suite() -> [{require,Name,{unix,[telnet]}}].

    or

    ct:require(Name,{unix,[telnet]}).

    The "keep alive" activity (that is, that Common Test sends NOP to the server every 10 seconds if the connection is idle) can be enabled or disabled for one particular connection as described here. It can be disabled for all connections using telnet_settings (see ct_telnet).

    The {port,PortNum} tuple is optional and if omitted, default Telnet port 23 is /usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/write_test_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1666)) --- old//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/write_test_chapter.html 2026-08-21 04:00:19.606295952 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/common_test-1.30.0.1/doc/html/write_test_chapter.html 2026-08-21 04:00:19.606295952 +0000 @@ -194,29 +194,29 @@ system configuration files, the test case is skipped.

    A required variable can also be given a default value to be used if the variable is not found in any configuration file. To specify a default value, add a tuple of the form {default_config,ConfigVariableName,Value} to the -test case information list (the position in the list is irrelevant).

    Examples:

    testcase1() ->
    -    [{require, ftp},
    -     {default_config, ftp, [{ftp, "my_ftp_host"},
    -                            {username, "aladdin"},
    -                            {password, "sesame"}]}}].
    testcase2() ->
    -    [{require, unix_telnet, unix},
    -     {require, {unix, [telnet, username, password]}},
    -     {default_config, unix, [{telnet, "my_telnet_host"},
    -                             {username, "aladdin"},
    -                             {password, "sesame"}]}}].

    For more information about require, see section +test case information list (the position in the list is irrelevant).

    Examples:

    testcase1() ->
    +    [{require, ftp},
    +     {default_config, ftp, [{ftp, "my_ftp_host"},
    +                            {username, "aladdin"},
    +                            {password, "sesame"}]}}].
    testcase2() ->
    +    [{require, unix_telnet, unix},
    +     {require, {unix, [telnet, username, password]}},
    +     {default_config, unix, [{telnet, "my_telnet_host"},
    +                             {username, "aladdin"},
    +                             {password, "sesame"}]}}].

    For more information about require, see section Requiring and Reading Configuration Data in section External Configuration Data and function ct:require/1/2.

    Note

    Specifying a default value for a required variable can result in a test case always getting executed. This might not be a desired behavior.

    If timetrap or require, or both, is not set specifically for a particular test case, default values specified by function -suite/0 are used.

    Tags other than the earlier mentioned are ignored by the test server.

    An example of a test case information function follows:

    reboot_node() ->
    -    [
    -     {timetrap,{seconds,60}},
    -     {require,interfaces},
    -     {userdata,
    -         [{description,"System Upgrade: RpuAddition Normal RebootNode"},
    -          {fts,"http://someserver.ericsson.se/test_doc4711.pdf"}]}
    -    ].

    Test Suite Information Function

    Function suite/0 can, for example, be used in a test +suite/0 are used.

    Tags other than the earlier mentioned are ignored by the test server.

    An example of a test case information function follows:

    reboot_node() ->
    +    [
    +     {timetrap,{seconds,60}},
    +     {require,interfaces},
    +     {userdata,
    +         [{description,"System Upgrade: RpuAddition Normal RebootNode"},
    +          {fts,"http://someserver.ericsson.se/test_doc4711.pdf"}]}
    +    ].

    Test Suite Information Function

    Function suite/0 can, for example, be used in a test suite module to set a default timetrap value and to require external configuration data. If a test case, or a group information function also specifies any of the information tags, it overrides the default values set by @@ -224,14 +224,14 @@ Test Case Information Function and Test Case Groups.

    The following options can also be specified with the suite information list:

    An example of the suite information function follows:

    suite() ->
    -    [
    -     {timetrap,{minutes,10}},
    -     {require,global_names},
    -     {userdata,[{info,"This suite tests database transactions."}]},
    -     {silent_connections,[telnet]},
    -     {stylesheet,"db_testing.css"}
    -    ].

    Test Case Groups

    A test case group is a set of test cases sharing configuration functions and +Silent Connections

    An example of the suite information function follows:

    suite() ->
    +    [
    +     {timetrap,{minutes,10}},
    +     {require,global_names},
    +     {userdata,[{info,"This suite tests database transactions."}]},
    +     {silent_connections,[telnet]},
    +     {stylesheet,"db_testing.css"}
    +    ].

    Test Case Groups

    A test case group is a set of test cases sharing configuration functions and execution properties. Test case groups are defined by function groups/0 that should return a term having the following syntax:

    groups() -> GroupDefs
    @@ -247,20 +247,20 @@
     TCRepeatProps = [{repeat,N} | {repeat_until_ok,N} | {repeat_until_fail,N}]

    GroupName is the name of the group and must be unique within the test suite module. Groups can be nested, by including a group definition within the GroupsAndTestCases list of another group. Properties is the list of -execution properties for the group. The possible values are as follows:

    Properties = [parallel | sequence | Shuffle | {GroupRepeatType,N}]
    -Shuffle = shuffle | {shuffle,Seed}
    -Seed = {integer(),integer(),integer()}
    +execution properties for the group. The possible values are as follows:

    Properties = [parallel | sequence | Shuffle | {GroupRepeatType,N}]
    +Shuffle = shuffle | {shuffle,Seed}
    +Seed = {integer(),integer(),integer()}
     GroupRepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
                       repeat_until_any_ok | repeat_until_any_fail
    -N = integer() | forever

    Explanations:

    • parallel - Common Test executes all test cases in the group in +N = integer() | forever

    Explanations:

    • parallel - Common Test executes all test cases in the group in parallel.

    • sequence - The cases are executed in a sequence as described in section Sequences in section Dependencies Between Test Cases and Suites.

    • shuffle - The cases in the group are executed in random order.

    • repeat, repeat_until_* - Orders Common Test to repeat execution of all the cases in the group a given number of times, or until any, or all, cases -fail or succeed.

    Example:

    groups() -> [{group1, [parallel], [test1a,test1b]},
    -             {group2, [shuffle,sequence], [test2a,test2b,test2c]}].

    To specify in which order groups are to be executed (also with respect to test +fail or succeed.

    Example:

    groups() -> [{group1, [parallel], [test1a,test1b]},
    +             {group2, [shuffle,sequence], [test2a,test2b,test2c]}].

    To specify in which order groups are to be executed (also with respect to test cases that are not part of any group), add tuples on the form -{group,GroupName} to the all/0 list.

    Example:

    all() -> [testcase1, {group,group1}, {testcase,testcase2,[{repeat,10}]}, {group,group2}].

    Execution properties with a group tuple in all/0: +{group,GroupName} to the all/0 list.

    Example:

    all() -> [testcase1, {group,group1}, {testcase,testcase2,[{repeat,10}]}, {group,group2}].

    Execution properties with a group tuple in all/0: {group,GroupName,Properties} can also be specified. These properties override those specified in the group definition (see groups/0 earlier). This way, the same set of tests can be run, but with different properties, without having to @@ -269,33 +269,33 @@ SubGroups is a list of tuples, {GroupName,Properties} or {GroupName,Properties,SubGroups} representing the subgroups. Any subgroups defined in groups/0 for a group, that are not specified in the SubGroups -list, executes with their predefined properties.

    Example:

    groups() -> [{tests1, [], [{tests2, [], [t2a,t2b]},
    -                          {tests3, [], [t31,t3b]}]}].

    To execute group tests1 twice with different properties for tests2 each -time:

    all() ->
    -   [{group, tests1, default, [{tests2, [parallel]}]},
    -    {group, tests1, default, [{tests2, [shuffle,{repeat,10}]}]}].

    This is equivalent to the following specification:

    all() ->
    -   [{group, tests1, default, [{tests2, [parallel]},
    -                              {tests3, default}]},
    -    {group, tests1, default, [{tests2, [shuffle,{repeat,10}]},
    -                              {tests3, default}]}].

    Value default states that the predefined properties are to be used.

    The following example shows how to override properties in a scenario with deeply -nested groups:

    groups() ->
    -   [{tests1, [], [{group, tests2}]},
    -    {tests2, [], [{group, tests3}]},
    -    {tests3, [{repeat,2}], [t3a,t3b,t3c]}].
    +list, executes with their predefined properties.

    Example:

    groups() -> [{tests1, [], [{tests2, [], [t2a,t2b]},
    +                          {tests3, [], [t31,t3b]}]}].

    To execute group tests1 twice with different properties for tests2 each +time:

    all() ->
    +   [{group, tests1, default, [{tests2, [parallel]}]},
    +    {group, tests1, default, [{tests2, [shuffle,{repeat,10}]}]}].

    This is equivalent to the following specification:

    all() ->
    +   [{group, tests1, default, [{tests2, [parallel]},
    +                              {tests3, default}]},
    +    {group, tests1, default, [{tests2, [shuffle,{repeat,10}]},
    +                              {tests3, default}]}].

    Value default states that the predefined properties are to be used.

    The following example shows how to override properties in a scenario with deeply +nested groups:

    groups() ->
    +   [{tests1, [], [{group, tests2}]},
    +    {tests2, [], [{group, tests3}]},
    +    {tests3, [{repeat,2}], [t3a,t3b,t3c]}].
     
    -all() ->
    -   [{group, tests1, default,
    -     [{tests2, default,
    -       [{tests3, [parallel,{repeat,100}]}]}]}].

    For ease of readability, all syntax definitions can be replaced by a function -call whose return value should match the expected syntax case.

    Example:

    all() ->
    -   [{group, tests1, default, test_cases()},
    -    {group, tests1, default, [shuffle_test(),
    -                              {tests3, default}]}].
    -test_cases() ->
    -   [{tests2, [parallel]}, {tests3, default}].
    +all() ->
    +   [{group, tests1, default,
    +     [{tests2, default,
    +       [{tests3, [parallel,{repeat,100}]}]}]}].

    For ease of readability, all syntax definitions can be replaced by a function +call whose return value should match the expected syntax case.

    Example:

    all() ->
    +   [{group, tests1, default, test_cases()},
    +    {group, tests1, default, [shuffle_test(),
    +                              {tests3, default}]}].
    +test_cases() ->
    +   [{tests2, [parallel]}, {tests3, default}].
     
    -shuffle_test() ->
    -   {tests2, [shuffle,{repeat,10}]}.

    The described syntax can also be used in test specifications to change group +shuffle_test() -> + {tests2, [shuffle,{repeat,10}]}.

    The described syntax can also be used in test specifications to change group properties at the time of execution, without having to edit the test suite. For more information, see section Test Specifications in section @@ -321,13 +321,13 @@ bottom of the log for end_per_group/2.

    Test case groups can be nested so sets of groups can be configured with the same init_per_group/2 and end_per_group/2 functions. Nested groups can be defined by including a group definition, or a group name reference, in the test case -list of another group.

    Example:

    groups() -> [{group1, [shuffle], [test1a,
    -                                  {group2, [], [test2a,test2b]},
    -                                  test1b]},
    -             {group3, [], [{group,group4},
    -                           {group,group5}]},
    -             {group4, [parallel], [test4a,test4b]},
    -             {group5, [sequence], [test5a,test5b,test5c]}].

    In the previous example, if all/0 returns group name references in the order +list of another group.

    Example:

    groups() -> [{group1, [shuffle], [test1a,
    +                                  {group2, [], [test2a,test2b]},
    +                                  test1b]},
    +             {group3, [], [{group,group4},
    +                           {group,group5}]},
    +             {group4, [parallel], [test4a,test4b]},
    +             {group5, [sequence], [test5a,test5b,test5c]}].

    In the previous example, if all/0 returns group name references in the order [{group,group1},{group,group3}], the order of the configuration functions and test cases becomes the following (notice that init_per_testcase/2 and end_per_testcase/2: are also always called, but not included in this example @@ -382,25 +382,25 @@ account by Common Test when evaluating if execution of a group is to be repeated or not (unless the basic repeat property is used).

    The value of tc_group_properties is a list of status tuples, each with the key ok, skipped, and failed. The value of a status tuple is a list with names -of test cases that have been executed with the corresponding status as result.

    The following is an example of how to return the status from a group:

    end_per_group(_Group, Config) ->
    -    Status = proplists:get_value(tc_group_result, Config),
    -    case proplists:get_value(failed, Status) of
    -        [] ->                                   % no failed cases
    -            {return_group_result,ok};
    +of test cases that have been executed with the corresponding status as result.

    The following is an example of how to return the status from a group:

    end_per_group(_Group, Config) ->
    +    Status = proplists:get_value(tc_group_result, Config),
    +    case proplists:get_value(failed, Status) of
    +        [] ->                                   % no failed cases
    +            {return_group_result,ok};
             _Failed ->                              % one or more failed
    -            {return_group_result,failed}
    +            {return_group_result,failed}
         end.

    It is also possible, in end_per_group/2, to check the status of a subgroup (maybe to determine what status the current group is to return). This is as /usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/beam_ssa.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/beam_ssa.html 2026-08-21 04:00:19.625296076 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/beam_ssa.html 2026-08-21 04:00:19.627296089 +0000 @@ -146,8 +146,8 @@ br ^common_end_of_catch common_end_of_catch: - @tmp = phi { @catched_val, ^landing_pad_block }, - { @successful_result, ^protected_blockN } + @tmp = phi { @catched_val, ^landing_pad_block }, + { @successful_result, ^protected_blockN } @result_of_catch_expr = catch_end @tag, @tmp

    Just as for a try-catch expression all code that can cause an exception in one of the protected blocks must have explicit control flow edges to the landing pad block.

    Exception Re-issuing

    A typical user-written try-catch expression will catch a subset of @@ -174,7 +174,7 @@ succeeded:body-instruction unless one of the following exceptions apply:

    • The function call can statically be proven to always fail.

    • The function call is to the erlang-module and can statically be proven to always succeed or fail.

    Variable Naming

    A variable name in BEAM SSA is either an atom or a non-negative -integer:

    atom() | non_neg_integer()

    In order to generate fresh unused variable names, all compiler +integer:

    atom() | non_neg_integer()

    In order to generate fresh unused variable names, all compiler transforms maintain a counter, the cnt-field in the b_function and opt_st records, which is incremented each time a new variable or label is created. In the following description the value of the /usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compile.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1750)) --- old//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compile.html 2026-08-21 04:00:19.655296271 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compile.html 2026-08-21 04:00:19.655296271 +0000 @@ -106,7 +106,7 @@ compiler recursively from inside a parse transform.

    The list can be retrieved with env_compiler_options/0.

    Order of Compiler Options

    Options given in the compile() attribute in the source code take precedence over options given to the compiler, which in turn take precedence over options given in the environment.

    A later compiler option takes precedence over an earlier one in the -option list. Example:

    compile:file(something, [nowarn_missing_spec,warn_missing_spec]).

    Warnings will be emitted for functions without specifications, unless +option list. Example:

    compile:file(something, [nowarn_missing_spec,warn_missing_spec]).

    Warnings will be emitted for functions without specifications, unless the source code for module something contains a compile(nowarn_missing_spec) attribute.

    Change

    In Erlang/OTP 26 and earlier, the option order was the opposite of what is described here.

    Inlining

    The compiler can do function inlining within an Erlang @@ -124,14 +124,14 @@ which functions to inline, or {inline,[{Name,Arity},...]} to have the compiler inline all calls to the given functions. If the option is given inside a compile directive in an Erlang module, {Name,Arity} can be written as -Name/Arity.

    Example of explicit inlining:

    -compile({inline,[pi/0]}).
    +Name/Arity.

    Example of explicit inlining:

    -compile({inline,[pi/0]}).
     
    -pi() -> 3.1416.

    Example of implicit inlining:

    -compile(inline).

    The option {inline_size,Size} controls how large functions that are allowed to +pi() -> 3.1416.

    Example of implicit inlining:

    -compile(inline).

    The option {inline_size,Size} controls how large functions that are allowed to be inlined. Default is 24, which keeps the size of the inlined code roughly the same as the un-inlined version (only relatively small functions are inlined).

    Example:

    %% Aggressive inlining - will increase code size.
    --compile(inline).
    --compile({inline_size,100}).

    Inlining of List Functions

    The compiler can also inline various list manipulation functions from the module +-compile(inline). +-compile({inline_size,100}).

    Inlining of List Functions

    The compiler can also inline various list manipulation functions from the module list in STDLIB.

    This feature must be explicitly enabled with a compiler option or a -compile() attribute in the source module.

    To enable inlining of list functions, use option inline_list_funcs.

    The following functions are inlined:

    Parse Transformations

    Parse transformations are used when a programmer wants to use Erlang syntax but with different semantics. The original Erlang code is then transformed into @@ -861,10 +861,10 @@ function definitions. This is the preferred method of enabling and disabling features, since it is a local property of a module.

  • makedep - Produces a Makefile rule to track headers dependencies. No object file is produced.

    By default, this rule is written to <File>.Pbeam. However, if option -binary is set, nothing is written and the rule is returned in Binary.

    The output will be encoded in UTF-8.

    For example, if you have the following module:

    -module(module).
    +binary is set, nothing is written and the rule is returned in Binary.

    The output will be encoded in UTF-8.

    For example, if you have the following module:

    -module(module).
     
    --include_lib("eunit/include/eunit.hrl").
    --include("header.hrl").

    The Makefile rule generated by this option looks as follows:

    module.beam: module.erl \
    +-include_lib("eunit/include/eunit.hrl").
    +-include("header.hrl").

    The Makefile rule generated by this option looks as follows:

    module.beam: module.erl \
       /usr/local/lib/erlang/lib/eunit/include/eunit.hrl \
       header.hrl
  • makedep_side_effect - The dependencies are created as a side effect to the normal compilation process. This means that the object file will also be @@ -930,7 +930,7 @@ before Erlang/OTP R14A when calling a local function with the same name as an auto-imported BIF without module prefix.

    If the BIF is to be called, use the erlang module prefix in the call, not {no_auto_import,[{F,A}, ...]}.

    If this option is written in the source code, as a -compile directive, the -syntax F/A can be used instead of {F,A}. For example:

    -compile({no_auto_import,[error/1]}).
  • no_auto_import - Do not auto-import any functions from erlang module.

  • no_line_info - Omits line number information to produce a slightly +syntax F/A can be used instead of {F,A}. For example:

    -compile({no_auto_import,[error/1]}).
  • no_auto_import - Do not auto-import any functions from erlang module.

  • no_line_info - Omits line number information to produce a slightly smaller output file.

  • no_lint - Skips the pass that checks for errors and warnings. Only applicable together with the from_abstr option. This is mainly for implementations of other languages on top of Erlang, which have already done /usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/beam_ssa.xhtml differs (HTML document, ASCII text, with very long lines (551)) --- old//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/beam_ssa.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/beam_ssa.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -74,8 +74,8 @@ br ^common_end_of_catch common_end_of_catch: - @tmp = phi { @catched_val, ^landing_pad_block }, - { @successful_result, ^protected_blockN } + @tmp = phi { @catched_val, ^landing_pad_block }, + { @successful_result, ^protected_blockN } @result_of_catch_expr = catch_end @tag, @tmp

  • Just as for a try-catch expression all code that can cause an exception in one of the protected blocks must have explicit control flow edges to the landing pad block.

    Exception Re-issuing

    A typical user-written try-catch expression will catch a subset of @@ -102,7 +102,7 @@ succeeded:body-instruction unless one of the following exceptions apply:

    • The function call can statically be proven to always fail.

    • The function call is to the erlang-module and can statically be proven to always succeed or fail.

    Variable Naming

    A variable name in BEAM SSA is either an atom or a non-negative -integer:

    atom() | non_neg_integer()

    In order to generate fresh unused variable names, all compiler +integer:

    atom() | non_neg_integer()

    In order to generate fresh unused variable names, all compiler transforms maintain a counter, the cnt-field in the b_function and opt_st records, which is incremented each time a new variable or label is created. In the following description the value of the /usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/compile.xhtml differs (HTML document, ASCII text, with very long lines (1495)) --- old//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/compile.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/compile.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -35,7 +35,7 @@ compiler recursively from inside a parse transform.

    The list can be retrieved with env_compiler_options/0.

    Order of Compiler Options

    Options given in the compile() attribute in the source code take precedence over options given to the compiler, which in turn take precedence over options given in the environment.

    A later compiler option takes precedence over an earlier one in the -option list. Example:

    compile:file(something, [nowarn_missing_spec,warn_missing_spec]).

    Warnings will be emitted for functions without specifications, unless +option list. Example:

    compile:file(something, [nowarn_missing_spec,warn_missing_spec]).

    Warnings will be emitted for functions without specifications, unless the source code for module something contains a compile(nowarn_missing_spec) attribute.

    Change

    In Erlang/OTP 26 and earlier, the option order was the opposite of what is described here.

    Inlining

    The compiler can do function inlining within an Erlang @@ -53,14 +53,14 @@ which functions to inline, or {inline,[{Name,Arity},...]} to have the compiler inline all calls to the given functions. If the option is given inside a compile directive in an Erlang module, {Name,Arity} can be written as -Name/Arity.

    Example of explicit inlining:

    -compile({inline,[pi/0]}).
    +Name/Arity.

    Example of explicit inlining:

    -compile({inline,[pi/0]}).
     
    -pi() -> 3.1416.

    Example of implicit inlining:

    -compile(inline).

    The option {inline_size,Size} controls how large functions that are allowed to +pi() -> 3.1416.

    Example of implicit inlining:

    -compile(inline).

    The option {inline_size,Size} controls how large functions that are allowed to be inlined. Default is 24, which keeps the size of the inlined code roughly the same as the un-inlined version (only relatively small functions are inlined).

    Example:

    %% Aggressive inlining - will increase code size.
    --compile(inline).
    --compile({inline_size,100}).

    Inlining of List Functions

    The compiler can also inline various list manipulation functions from the module +-compile(inline). +-compile({inline_size,100}).

    Inlining of List Functions

    The compiler can also inline various list manipulation functions from the module list in STDLIB.

    This feature must be explicitly enabled with a compiler option or a -compile() attribute in the source module.

    To enable inlining of list functions, use option inline_list_funcs.

    The following functions are inlined:

    Parse Transformations

    Parse transformations are used when a programmer wants to use Erlang syntax but with different semantics. The original Erlang code is then transformed into @@ -774,10 +774,10 @@ function definitions. This is the preferred method of enabling and disabling features, since it is a local property of a module.

  • makedep - Produces a Makefile rule to track headers dependencies. No object file is produced.

    By default, this rule is written to <File>.Pbeam. However, if option -binary is set, nothing is written and the rule is returned in Binary.

    The output will be encoded in UTF-8.

    For example, if you have the following module:

    -module(module).
    +binary is set, nothing is written and the rule is returned in Binary.

    The output will be encoded in UTF-8.

    For example, if you have the following module:

    -module(module).
     
    --include_lib("eunit/include/eunit.hrl").
    --include("header.hrl").

    The Makefile rule generated by this option looks as follows:

    module.beam: module.erl \
    +-include_lib("eunit/include/eunit.hrl").
    +-include("header.hrl").

    The Makefile rule generated by this option looks as follows:

    module.beam: module.erl \
       /usr/local/lib/erlang/lib/eunit/include/eunit.hrl \
       header.hrl
  • makedep_side_effect - The dependencies are created as a side effect to the normal compilation process. This means that the object file will also be @@ -843,7 +843,7 @@ before Erlang/OTP R14A when calling a local function with the same name as an auto-imported BIF without module prefix.

    If the BIF is to be called, use the erlang module prefix in the call, not {no_auto_import,[{F,A}, ...]}.

    If this option is written in the source code, as a -compile directive, the -syntax F/A can be used instead of {F,A}. For example:

    -compile({no_auto_import,[error/1]}).
  • no_auto_import - Do not auto-import any functions from erlang module.

  • no_line_info - Omits line number information to produce a slightly +syntax F/A can be used instead of {F,A}. For example:

    -compile({no_auto_import,[error/1]}).
  • no_auto_import - Do not auto-import any functions from erlang module.

  • no_line_info - Omits line number information to produce a slightly smaller output file.

  • no_lint - Skips the pass that checks for errors and warnings. Only applicable together with the from_abstr option. This is mainly for implementations of other languages on top of Erlang, which have already done /usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> compiler - 9.0.6.1 - urn:uuid:aa6d9e26-74ca-a919-f933-22e89a3e84f0 + urn:uuid:d87d9890-1fc5-fae0-2025-9b7959da571c en - 2026-08-21T03:47:38Z + 2042-09-22T17:06:17Z /usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/notes.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (8735)) --- old//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -17,48 +17,48 @@

    Compiler Release Notes

    -

    This document describes the changes made to the Compiler application.

    Compiler 9.0.6.1

    Fixed Bugs and Malfunctions

    • In rare circumstances, optimization of boolean expressions could invert the boolean value.

      Own Id: OTP-20140 Aux Id: GH-11088, PR-11089

    Compiler 9.0.6

    Fixed Bugs and Malfunctions

    • The type inference for maps:from_list/1 was incorrect: when the provided list was statically known to be bogus when non-empty (e.g. a list of atoms), the compiler assumed it would also fail when the list was empty.

      Own Id: OTP-19506 Aux Id: GH-9476, PR-9481

    • Fixed a bug in the type analysis pass that could erroneously eliminate code blocks.

      Own Id: OTP-19931 Aux Id: GH-10562, PR-10569

    • A binary as the value of a -moduledoc() attribute would be silently ignored.

      Own Id: OTP-20065 Aux Id: GH-10901, PR-10904

    Compiler 9.0.5

    Fixed Bugs and Malfunctions

    • Fixed a compiler alias analysis bug that could generate unsafe code for repeated binary segments.

      Own Id: OTP-19951 Aux Id: PR-10588

    Compiler 9.0.4

    Fixed Bugs and Malfunctions

    • For some function heads or case expressions with a huge number of clauses, the compiler could spend an inordinate amount of time compiling the code.

      Own Id: OTP-19797 Aux Id: PR-10252

    • Passing a type for a fun as a macro argument would result in a "badly formed argument" error message from the compiler. Example:

      -module(test).
      --define(FOO(X), X).
      --type foo() :: ?FOO(fun(() -> ok)).

      Compiling this module would result in the following error message:

      test.erl:3:17: badly formed argument for macro 'FOO'
      +

      This document describes the changes made to the Compiler application.

      Compiler 9.0.6.1

      Fixed Bugs and Malfunctions

      • In rare circumstances, optimization of boolean expressions could invert the boolean value.

        Own Id: OTP-20140 Aux Id: GH-11088, PR-11089

      Compiler 9.0.6

      Fixed Bugs and Malfunctions

      • The type inference for maps:from_list/1 was incorrect: when the provided list was statically known to be bogus when non-empty (e.g. a list of atoms), the compiler assumed it would also fail when the list was empty.

        Own Id: OTP-19506 Aux Id: GH-9476, PR-9481

      • Fixed a bug in the type analysis pass that could erroneously eliminate code blocks.

        Own Id: OTP-19931 Aux Id: GH-10562, PR-10569

      • A binary as the value of a -moduledoc() attribute would be silently ignored.

        Own Id: OTP-20065 Aux Id: GH-10901, PR-10904

      Compiler 9.0.5

      Fixed Bugs and Malfunctions

      • Fixed a compiler alias analysis bug that could generate unsafe code for repeated binary segments.

        Own Id: OTP-19951 Aux Id: PR-10588

      Compiler 9.0.4

      Fixed Bugs and Malfunctions

      • For some function heads or case expressions with a huge number of clauses, the compiler could spend an inordinate amount of time compiling the code.

        Own Id: OTP-19797 Aux Id: PR-10252

      • Passing a type for a fun as a macro argument would result in a "badly formed argument" error message from the compiler. Example:

        -module(test).
        +-define(FOO(X), X).
        +-type foo() :: ?FOO(fun(() -> ok)).

        Compiling this module would result in the following error message:

        test.erl:3:17: badly formed argument for macro 'FOO'
         %    5| -type foo() :: ?FOO(fun(() -> ok)).
        -%

        Own Id: OTP-19821 Aux Id: GH-10280, PR-10309

      • In certain edge cases, the compiler could emit code that would do an unsafe destructive update of a tuple. This has been corrected.

        Own Id: OTP-19879 Aux Id: GH-10367, PR-10435

      Improvements and New Features

      • The compiler option beam_debug_stack combined with beam_debug_info will attempt to make as many variables as possible visible in the debugger. The option has no effect if given without beam_debug_info.

        Own Id: OTP-19854 Aux Id: PR-10374

      Compiler 9.0.3

      Fixed Bugs and Malfunctions

      • Fixed broken type inference for lists:mapfoldl/r.

        Own Id: OTP-19845 Aux Id: GH-10354, PR-10358

      Compiler 9.0.2

      Fixed Bugs and Malfunctions

      • Fixed a compiler crash caused by patch order in destructive update.

        Own Id: OTP-19660 Aux Id: GH-9903, PR-9909

      • Fixed a compiler crash in beam_ssa_pre_codegen caused by wrong handling of multiple phi patches in the destructive update pass.

        Own Id: OTP-19689 Aux Id: GH-9987, PR-9990

      • Fixed a crash when a zip generator contains a map pattern.

        Own Id: OTP-19693 Aux Id: PR-10009, GH-10002

      • In rare circumstances, the compiler could crash when compiling code using bit syntax construction.

        Own Id: OTP-19722 Aux Id: GH-10077, PR-10090

      • A few minor bugs that could affect the beam_debug_info option were fixed.

        Own Id: OTP-19758 Aux Id: PR-10153

      Compiler 9.0.1

      Fixed Bugs and Malfunctions

      • Fixed a bug that could cause empty bitstring matches to always succeed, even when they should not.

        Own Id: OTP-19711 Aux Id: GH-10047, PR-10048

      Compiler 9.0

      Fixed Bugs and Malfunctions

      • The compiler will now emit warnings when some map patterns cannot possibly match because a previous clauses matches the same pattern. For example:

        mm_1(#{}) -> a;
        -mm_1(#{b := B}) -> {b,B}.
        +%

        Own Id: OTP-19821 Aux Id: GH-10280, PR-10309

      • In certain edge cases, the compiler could emit code that would do an unsafe destructive update of a tuple. This has been corrected.

        Own Id: OTP-19879 Aux Id: GH-10367, PR-10435

      Improvements and New Features

      • The compiler option beam_debug_stack combined with beam_debug_info will attempt to make as many variables as possible visible in the debugger. The option has no effect if given without beam_debug_info.

        Own Id: OTP-19854 Aux Id: PR-10374

      Compiler 9.0.3

      Fixed Bugs and Malfunctions

      • Fixed broken type inference for lists:mapfoldl/r.

        Own Id: OTP-19845 Aux Id: GH-10354, PR-10358

      Compiler 9.0.2

      Fixed Bugs and Malfunctions

      • Fixed a compiler crash caused by patch order in destructive update.

        Own Id: OTP-19660 Aux Id: GH-9903, PR-9909

      • Fixed a compiler crash in beam_ssa_pre_codegen caused by wrong handling of multiple phi patches in the destructive update pass.

        Own Id: OTP-19689 Aux Id: GH-9987, PR-9990

      • Fixed a crash when a zip generator contains a map pattern.

        Own Id: OTP-19693 Aux Id: PR-10009, GH-10002

      • In rare circumstances, the compiler could crash when compiling code using bit syntax construction.

        Own Id: OTP-19722 Aux Id: GH-10077, PR-10090

      • A few minor bugs that could affect the beam_debug_info option were fixed.

        Own Id: OTP-19758 Aux Id: PR-10153

      Compiler 9.0.1

      Fixed Bugs and Malfunctions

      • Fixed a bug that could cause empty bitstring matches to always succeed, even when they should not.

        Own Id: OTP-19711 Aux Id: GH-10047, PR-10048

      Compiler 9.0

      Fixed Bugs and Malfunctions

      • The compiler will now emit warnings when some map patterns cannot possibly match because a previous clauses matches the same pattern. For example:

        mm_1(#{}) -> a;
        +mm_1(#{b := B}) -> {b,B}.
         
        -mm_2(#{a := A}) -> {a,A};
        -mm_2(#{a := A, b := B}) -> {b,A,B}.

        The second clause of these function can never match and the compiler will now emit a warning for both of them.

        Note that the compiler is not guaranteed to emit warnings for every possible map pattern that cannot match.

        Own Id: OTP-19141 Aux Id: GH-8558, PR-8600

      • The size of an atom in the Erlang source code was limited to 255 bytes in previous releases, meaning that an atom containing only emojis could contain only 63 emojis.

        While atoms are still only allowed to contain 255 characters, the number of bytes is no longer limited.

        External tools that parse the AtU8 chunk of a BEAM file directly need to be updated. Tools that use beam_lib:chunks(Beam, [atoms]) to read the atom table will continue to work.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19285 Aux Id: PR-8913

      • The literals chunk in BEAM is no longer compressed, resulting in slightly smaller BEAM files when a BEAM file is stripped using beam_lib:strip_files/1.

        This is a potential incompatibility for tools that read and interpret the contents of the literal chunk. One way to update such tools to work with the new format is to retrieve the chunk using beam_lib:chunks(Beam, [literals]).

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19323 Aux Id: GH-8967, PR-8988

      • The final validation step in the compiler will now reject modules containing functions with more than 255 arguments. No impact is expected as the emulator has always refused to load these modules.

        Own Id: OTP-19376 Aux Id: GH-9113, PR-9121

      • Replaced calls to deprecated crypto:start() with application:start(crypto).

        Own Id: OTP-19485 Aux Id: PR-8592

      • Refactor code to not rely on +nowarn_shadow_vars.

        Own Id: OTP-19574 Aux Id: PR-9678

      Improvements and New Features

      • The EEP-48 doc chunk embedded into .beam files by the compiler is now compressed and deterministic.

        Own Id: OTP-19096 Aux Id: PR-8494

      • Provided that the map argument for a maps:put/3 call is known to the compiler to be a map, the compiler will replace such calls with the corresponding update using the map syntax.

        Own Id: OTP-19115 Aux Id: PR-8540

      • For various error types, the compiler now tries to suggest potential fixes by adding "did you mean ...?" at the end of error messages.

        When a function is used with wrong arity, the compiler will try to suggest a defined function with the same name but a different arity. For example, given the following module:

        -module(typos).
        --export([t/0]).
        -bar(A) -> A.
        -bar(A,A,A) -> A.
        -bar(A,A,A,A) -> A.
        -t() -> bar(0, 0).

        The compiler will emit the following message:

        typo.erl:6:12: function bar/2 undefined, did you mean bar/1,3,4?
        +mm_2(#{a := A}) -> {a,A};
        +mm_2(#{a := A, b := B}) -> {b,A,B}.

        The second clause of these function can never match and the compiler will now emit a warning for both of them.

        Note that the compiler is not guaranteed to emit warnings for every possible map pattern that cannot match.

        Own Id: OTP-19141 Aux Id: GH-8558, PR-8600

      • The size of an atom in the Erlang source code was limited to 255 bytes in previous releases, meaning that an atom containing only emojis could contain only 63 emojis.

        While atoms are still only allowed to contain 255 characters, the number of bytes is no longer limited.

        External tools that parse the AtU8 chunk of a BEAM file directly need to be updated. Tools that use beam_lib:chunks(Beam, [atoms]) to read the atom table will continue to work.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19285 Aux Id: PR-8913

      • The literals chunk in BEAM is no longer compressed, resulting in slightly smaller BEAM files when a BEAM file is stripped using beam_lib:strip_files/1.

        This is a potential incompatibility for tools that read and interpret the contents of the literal chunk. One way to update such tools to work with the new format is to retrieve the chunk using beam_lib:chunks(Beam, [literals]).

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19323 Aux Id: GH-8967, PR-8988

      • The final validation step in the compiler will now reject modules containing functions with more than 255 arguments. No impact is expected as the emulator has always refused to load these modules.

        Own Id: OTP-19376 Aux Id: GH-9113, PR-9121

      • Replaced calls to deprecated crypto:start() with application:start(crypto).

        Own Id: OTP-19485 Aux Id: PR-8592

      • Refactor code to not rely on +nowarn_shadow_vars.

        Own Id: OTP-19574 Aux Id: PR-9678

      Improvements and New Features

      • The EEP-48 doc chunk embedded into .beam files by the compiler is now compressed and deterministic.

        Own Id: OTP-19096 Aux Id: PR-8494

      • Provided that the map argument for a maps:put/3 call is known to the compiler to be a map, the compiler will replace such calls with the corresponding update using the map syntax.

        Own Id: OTP-19115 Aux Id: PR-8540

      • For various error types, the compiler now tries to suggest potential fixes by adding "did you mean ...?" at the end of error messages.

        When a function is used with wrong arity, the compiler will try to suggest a defined function with the same name but a different arity. For example, given the following module:

        -module(typos).
        +-export([t/0]).
        +bar(A) -> A.
        +bar(A,A,A) -> A.
        +bar(A,A,A,A) -> A.
        +t() -> bar(0, 0).

        The compiler will emit the following message:

        typo.erl:6:12: function bar/2 undefined, did you mean bar/1,3,4?
         %   6|     t() -> bar(0, 0).
        -%    |            ^

        For compiler errors that can easily be caused by typos, the compiler will try to suggest what the correct variable or function name, could be. For example, given the following module:

        -module(typos).
        --export([bar/2]).
        +%    |            ^

        For compiler errors that can easily be caused by typos, the compiler will try to suggest what the correct variable or function name, could be. For example, given the following module:

        -module(typos).
        +-export([bar/2]).
         
        -bar(A0, B0) ->
        +bar(A0, B0) ->
             A + B.

        the compiler will emit the following error messages:

        typos.erl:5:5: variable 'A' is unbound, did you mean 'A0'?
         %    5|     A + B.
         %     |     ^
         
         typos.erl:5:9: variable 'B' is unbound, did you mean 'B0'?
         %    5|     A + B.
        -%     |         ^

        Error types that now suggest correct arities: bad_inline, undefined_nif, bad_nowarn_unused_function, bad_nowarn_bif_clash, undefined_function.

        Error types that now suggest correct names: bad_inline, undefined_nif, bad_nowarn_unused_function, undefined_on_load, undefined_function, undefined_record, undefined_field, unbound_var.

        Using a function with wrong arity has higher precedence than having a typo in the function name. If the compiler can find a defined function with the same name but a different arity, it will not suggest a defined function with a close-enough name, regardless of arity.

        Own Id: OTP-19180 Aux Id: PR-8699, PR-9094

      • Comprehensions have been extended with zip generators according to EEP 73.

        Example:

        1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
        -[5,7,9]

        Own Id: OTP-19184 Aux Id: PR-8926

      • Documentation chunks (EEP-48) has been updated to include the following reserved metadata fields: behaviours, group, source_path, and source_annos. The compiler has also been updated to emit this metadata. See the EEP-48 documentation for more details.

        Own Id: OTP-19306 Aux Id: PR-8945, PR-8975

      • New strict generators have been added for comprehensions.

        The currently existing generators are "relaxed": they ignore terms in the +% | ^

      Error types that now suggest correct arities: bad_inline, undefined_nif, bad_nowarn_unused_function, bad_nowarn_bif_clash, undefined_function.

      Error types that now suggest correct names: bad_inline, undefined_nif, bad_nowarn_unused_function, undefined_on_load, undefined_function, undefined_record, undefined_field, unbound_var.

      Using a function with wrong arity has higher precedence than having a typo in the function name. If the compiler can find a defined function with the same name but a different arity, it will not suggest a defined function with a close-enough name, regardless of arity.

      Own Id: OTP-19180 Aux Id: PR-8699, PR-9094

    • Comprehensions have been extended with zip generators according to EEP 73.

      Example:

      1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
      +[5,7,9]

      Own Id: OTP-19184 Aux Id: PR-8926

    • Documentation chunks (EEP-48) has been updated to include the following reserved metadata fields: behaviours, group, source_path, and source_annos. The compiler has also been updated to emit this metadata. See the EEP-48 documentation for more details.

      Own Id: OTP-19306 Aux Id: PR-8945, PR-8975

    • New strict generators have been added for comprehensions.

      The currently existing generators are "relaxed": they ignore terms in the right-hand side expression that do not match the left-hand side pattern.

      The new strict generators fail with exception badmatch if a pattern doesn't match.

      Examples:

      Using the current relaxed generator operator <-, any element not matching -the pattern {_,_} will be silently discarded:

      1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
      -[{ok,1},{error,2}]

      If the intention is that all lists processed by a list comprehension must only +the pattern {_,_} will be silently discarded:

      1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
      +[{ok,1},{error,2}]

      If the intention is that all lists processed by a list comprehension must only contain tuples of size two, using the new strict version of the operator ensures -that term not matching will cause a crash:

      2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
      +that term not matching will cause a crash:

      2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
       ** exception error: no match of right hand side value ok

      Using the strict generator operator to mark the intention that all list elements must match the pattern could help finding mistakes quicker if something unpexected is added to the list processed by the generator.

      The strict version for bitstring generators is <:=.

      Own Id: OTP-19317 Aux Id: PR-8625

    • New options for suppressing behaviour warnings have been added:

      • nowarn_conflicting_behaviours
      • nowarn_undefined_behaviour_func
      • nowarn_undefined_behaviour
      • nowarn_undefined_behaviour_callbacks
      • nowarn_ill_defined_behaviour_callbacks
      • nowarn_ill_defined_optional_callbacks

      Own Id: OTP-19334 Aux Id: GH-8985, PR-9020

    • Some BIFs with side-effects are optimized in try/catch in the same way as guard BIFs in order to gain performance.

      The following BIFs that are optimized in this way: binary_to_atom/1, binary_to_atom/2, binary_to_existing_atom/1, list_to_atom/1, and -list_to_existing_atom/1.

      Own Id: OTP-19339 Aux Id: PR-9042, PR-9122

    • The compiler now converts known documentation attribute metadata entries from unicode:chardata/0 to unicode:unicode_binary/0.

      Own Id: OTP-19394 Aux Id: PR-9192

    • The warn_deprecated_catch option enables warnings for use of old-style catch expressions on the form catch Expr instead of the modern try ... catch ... end. To prevent new uses of uses of old catches to be added, this compiler option can be enabled on the project level and -compile(nowarn_deprecated_catch). added to individual files that still contain old catches.

      Own Id: OTP-19425 Aux Id: PR-9154

    • Defining a fun in terms of an imported function is not allowed. Before this release, the compiler would not catch this kind of error if the name of the imported function happened to be a BIF. Consider this example:

      -module(fun_example).
      --export([foo/0, bar/0]).
      --import(m, [max/2, not_a_bif/0]).
      +list_to_existing_atom/1.

      Own Id: OTP-19339 Aux Id: PR-9042, PR-9122

    • The compiler now converts known documentation attribute metadata entries from unicode:chardata/0 to unicode:unicode_binary/0.

      Own Id: OTP-19394 Aux Id: PR-9192

    • The warn_deprecated_catch option enables warnings for use of old-style catch expressions on the form catch Expr instead of the modern try ... catch ... end. To prevent new uses of uses of old catches to be added, this compiler option can be enabled on the project level and -compile(nowarn_deprecated_catch). added to individual files that still contain old catches.

      Own Id: OTP-19425 Aux Id: PR-9154

    • Defining a fun in terms of an imported function is not allowed. Before this release, the compiler would not catch this kind of error if the name of the imported function happened to be a BIF. Consider this example:

      -module(fun_example).
      +-export([foo/0, bar/0]).
      +-import(m, [max/2, not_a_bif/0]).
       
      -foo() ->
      +foo() ->
           fun max/2.
       
      -bar() ->
      +bar() ->
           fun not_a_bif/0.

      The compiler in Erlang/OTP 27 would generate the following messages:

      fun_example.erl:9:5: function not_a_bif/0 undefined
       %    9|     fun not_a_bif/0.
       %     |     ^
      @@ -77,60 +77,60 @@
       fun_example.erl:3:2: Warning: import directive overrides auto-imported BIF max/2 --
       use "-compile({no_auto_import,[max/2]})." to resolve name clash
       %    3| -import(m, [max/2, not_a_bif/0]).
      -%     |  ^

      Also, attempting to call a local function having the same name as auto-imported BIF would result in an error if the BIF was added to Erlang/OTP before R14, and a warning for newer BIFs. This has been changed to always emit a warning. For example:

      -module(bif_example).
      --export([bar/1]).
      +%     |  ^

      Also, attempting to call a local function having the same name as auto-imported BIF would result in an error if the BIF was added to Erlang/OTP before R14, and a warning for newer BIFs. This has been changed to always emit a warning. For example:

      -module(bif_example).
      +-export([bar/1]).
       
      -bar(B) ->
      -    is_boolean(B).
      +bar(B) ->
      +    is_boolean(B).
       
      -is_boolean(B) ->
      +is_boolean(B) ->
               B =:= true orelse B =:= false.

      will now result in the following warning instead of an error:

      if_example.erl:5:5: Warning: ambiguous call of overridden auto-imported BIF is_boolean/1 --
       use erlang:is_boolean/1 or "-compile({no_auto_import,[is_boolean/1]})." to resolve name clash
       %    5|     is_boolean(B).
      -%     |     ^

      Own Id: OTP-19432 Aux Id: PR-9246

    • The compiler’s alias analysis pass is now both faster and less conservative, allowing optimizations of records and binary construction to be applied in more cases.

      Own Id: OTP-19502 Aux Id: PR-8695

    • BEAM files no longer include a Meta chunk if there are no features used. That slightly decreases the size of BEAM files, and it also ensures that m(Module) and beam_lib:md5(Beam) will match for preloaded modules.

      Own Id: OTP-19524 Aux Id: PR-9517

    • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

      Own Id: OTP-19575 Aux Id: PR-9670

    • An experimental API for a native debugger has been added. The main components are the following:

      • A new compiler option beam_debug_info for the Erlang compiler. When given, most optimizations are disabled and debug information suitable for the native debugger are added to generated BEAM files.

      • A new +D emulator flag. When given, the VM becomes "debuggable", which means that when modules that been compiled with the beam_debug_info option are loaded, the code is instrumented so that one can enable and disable breakpoints on executable lines.

      • An experimental erl_debugger module with a new debugging API. Essentially, it allows a single, local, process to be registered as the "debugger" process for the node. This process is the one that will receive messages notifying that a process hit a breakpoint. This way, the front-end implementation of a debugger (such as edb from WhatApp) can be decoupled from OTP.

      • The erl_debugger module also exposes new BIFs to inspect X and Y registers of a suspended process. Together with new code-information BIFs, this let's a debugger show the values of variables in scope for a suspended process.

      Own Id: OTP-19609 Aux Id: PR-8670, PR-9334, PR-9604

    Compiler 8.6.1.4

    Fixed Bugs and Malfunctions

    • The type inference for maps:from_list/1 was incorrect: when the provided list was statically known to be bogus when non-empty (e.g. a list of atoms), the compiler assumed it would also fail when the list was empty.

      Own Id: OTP-19506 Aux Id: GH-9476, PR-9481

    • Fixed a bug in the type analysis pass that could erroneously eliminate code blocks.

      Own Id: OTP-19931 Aux Id: GH-10562, PR-10569

    • A binary as the value of a -moduledoc() attribute would be silently ignored.

      Own Id: OTP-20065 Aux Id: GH-10901, PR-10904

    Compiler 8.6.1.3

    Fixed Bugs and Malfunctions

    • Fixed broken type inference for lists:mapfoldl/r.

      Own Id: OTP-19845 Aux Id: GH-10354, PR-10358

    • Fix a compiler alias analysis bug that can generate unsafe code for repeated binary segments.

      Own Id: OTP-19951 Aux Id: PR-10588

    Compiler 8.6.1.2

    Fixed Bugs and Malfunctions

    • In rare circumstances, the compiler could crash when compiling code using bit syntax construction.

      Own Id: OTP-19722 Aux Id: GH-10077, PR-10090

    Compiler 8.6.1.1

    Fixed Bugs and Malfunctions

    • Fixed a bug that could cause empty bitstring matches to always succeed, even when they should not.

      Own Id: OTP-19711 Aux Id: GH-10047, PR-10048

    Compiler 8.6.1

    Fixed Bugs and Malfunctions

    • Fix the compiler crash when the inner-most tuple in a nested tuple with 3 layers is updated.

      Own Id: OTP-19561 Aux Id: ERIERL-1208, ERIERL-1210, PR-9650

    Compiler 8.6

    Improvements and New Features

    • The beam_validator pass in the compiler that validates generated BEAM now does stronger checks for binary syntax matching.

      Own Id: OTP-19449 Aux Id: PR-9338

    Compiler 8.5.5

    Fixed Bugs and Malfunctions

    • Eliminated a bug in the alias analysis pass that could potentially cause unsafe optimizations of binary construction or record updates.

      Own Id: OTP-19455 Aux Id: PR-9356

    Compiler 8.5.4

    Fixed Bugs and Malfunctions

    • Fixed a crash in the common sub-expression elimination pass.

      Own Id: OTP-19243 Aux Id: GH-8818, PR-8838

    • Fixed a bug where bogus code was generated for consecutive calls to erlang:setelement/2, potentially crashing the runtime system.

      Own Id: OTP-19270 Aux Id: GH-8783, PR-8898

    • When the line_coverage option was used, exceptions could show the wrong line for where the exception was raised.

      Own Id: OTP-19282 Aux Id: PR-8907

    • The line_coverage option would be ignored if given in a compile() attribute within a module.

      Own Id: OTP-19309 Aux Id: GH-8942, PR-8970

    • A segment matching a float in a binary generator will now skip any invalid float (such as a NaN) and continue matching the rest of the binary. Before this correction, the comprehension would stop as soon as an invalid float was encountered.

      Example:

      1> BadFloat = <<-1:64>>.
      -<<"ÿÿÿÿÿÿÿÿ">>
      -2> [X || <<X:64/float>> <= <<0.0/float,BadFloat/binary,42.0/float>>].
      -[0.0,42.0]

      Own Id: OTP-19331 Aux Id: PR-8978

    Compiler 8.5.3

    Fixed Bugs and Malfunctions

    • In rare circumstances, the destructive tuple update optimization could be applied when it was unsafe.

      Own Id: OTP-19340 Aux Id: GH-9014, PR-9024

    • In rare circumstances involving appending to multiple binaries, the compile could emit unsafe code that would crash the runtime system.

      Own Id: OTP-19374 Aux Id: GH-9100, PR-9111

    Compiler 8.5.2

    Fixed Bugs and Malfunctions

    • Fixed a crash in an optimization pass relating to appending binaries.

      Own Id: OTP-19168 Aux Id: GH-8630

    • Fixed a bug in the compiler's alias analysis pass that could make it emit unsafe code.

      Own Id: OTP-19178 Aux Id: PR-8686

    Compiler 8.5.1

    Fixed Bugs and Malfunctions

    • One of the compiler's optimization passes would get very slow when compiling certain modules. The compiler will now automatically disable that pass for input that would trigger the slowdown.

      Own Id: OTP-19131 Aux Id: PR-8567

    • Fix +deterministic to work properly with documentation attributes.

      Own Id: OTP-19142 Aux Id: PR-8585, GH-8579

    Compiler 8.5

    Fixed Bugs and Malfunctions

    • Generators for binary comprehensions could be evaluated before it was known that they would be needed. That could result in a binary comprehensions failing if a generator that should not be evaluated until later failed.

      As an example, consider this module:

      -module(t).
      --export([f/0]).
      +%     |     ^

      Own Id: OTP-19432 Aux Id: PR-9246

    • The compiler’s alias analysis pass is now both faster and less conservative, allowing optimizations of records and binary construction to be applied in more cases.

      Own Id: OTP-19502 Aux Id: PR-8695

    • BEAM files no longer include a Meta chunk if there are no features used. That slightly decreases the size of BEAM files, and it also ensures that m(Module) and beam_lib:md5(Beam) will match for preloaded modules.

      Own Id: OTP-19524 Aux Id: PR-9517

    • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

      Own Id: OTP-19575 Aux Id: PR-9670

    • An experimental API for a native debugger has been added. The main components are the following:

      • A new compiler option beam_debug_info for the Erlang compiler. When given, most optimizations are disabled and debug information suitable for the native debugger are added to generated BEAM files.

      • A new +D emulator flag. When given, the VM becomes "debuggable", which means that when modules that been compiled with the beam_debug_info option are loaded, the code is instrumented so that one can enable and disable breakpoints on executable lines.

      • An experimental erl_debugger module with a new debugging API. Essentially, it allows a single, local, process to be registered as the "debugger" process for the node. This process is the one that will receive messages notifying that a process hit a breakpoint. This way, the front-end implementation of a debugger (such as edb from WhatApp) can be decoupled from OTP.

      • The erl_debugger module also exposes new BIFs to inspect X and Y registers of a suspended process. Together with new code-information BIFs, this let's a debugger show the values of variables in scope for a suspended process.

      Own Id: OTP-19609 Aux Id: PR-8670, PR-9334, PR-9604

    Compiler 8.6.1.4

    Fixed Bugs and Malfunctions

    • The type inference for maps:from_list/1 was incorrect: when the provided list was statically known to be bogus when non-empty (e.g. a list of atoms), the compiler assumed it would also fail when the list was empty.

      Own Id: OTP-19506 Aux Id: GH-9476, PR-9481

    • Fixed a bug in the type analysis pass that could erroneously eliminate code blocks.

      Own Id: OTP-19931 Aux Id: GH-10562, PR-10569

    • A binary as the value of a -moduledoc() attribute would be silently ignored.

      Own Id: OTP-20065 Aux Id: GH-10901, PR-10904

    Compiler 8.6.1.3

    Fixed Bugs and Malfunctions

    • Fixed broken type inference for lists:mapfoldl/r.

      Own Id: OTP-19845 Aux Id: GH-10354, PR-10358

    • Fix a compiler alias analysis bug that can generate unsafe code for repeated binary segments.

      Own Id: OTP-19951 Aux Id: PR-10588

    Compiler 8.6.1.2

    Fixed Bugs and Malfunctions

    • In rare circumstances, the compiler could crash when compiling code using bit syntax construction.

      Own Id: OTP-19722 Aux Id: GH-10077, PR-10090

    Compiler 8.6.1.1

    Fixed Bugs and Malfunctions

    • Fixed a bug that could cause empty bitstring matches to always succeed, even when they should not.

      Own Id: OTP-19711 Aux Id: GH-10047, PR-10048

    Compiler 8.6.1

    Fixed Bugs and Malfunctions

    • Fix the compiler crash when the inner-most tuple in a nested tuple with 3 layers is updated.

      Own Id: OTP-19561 Aux Id: ERIERL-1208, ERIERL-1210, PR-9650

    Compiler 8.6

    Improvements and New Features

    • The beam_validator pass in the compiler that validates generated BEAM now does stronger checks for binary syntax matching.

      Own Id: OTP-19449 Aux Id: PR-9338

    Compiler 8.5.5

    Fixed Bugs and Malfunctions

    • Eliminated a bug in the alias analysis pass that could potentially cause unsafe optimizations of binary construction or record updates.

      Own Id: OTP-19455 Aux Id: PR-9356

    Compiler 8.5.4

    Fixed Bugs and Malfunctions

    • Fixed a crash in the common sub-expression elimination pass.

      Own Id: OTP-19243 Aux Id: GH-8818, PR-8838

    • Fixed a bug where bogus code was generated for consecutive calls to erlang:setelement/2, potentially crashing the runtime system.

      Own Id: OTP-19270 Aux Id: GH-8783, PR-8898

    • When the line_coverage option was used, exceptions could show the wrong line for where the exception was raised.

      Own Id: OTP-19282 Aux Id: PR-8907

    • The line_coverage option would be ignored if given in a compile() attribute within a module.

      Own Id: OTP-19309 Aux Id: GH-8942, PR-8970

    • A segment matching a float in a binary generator will now skip any invalid float (such as a NaN) and continue matching the rest of the binary. Before this correction, the comprehension would stop as soon as an invalid float was encountered.

      Example:

      1> BadFloat = <<-1:64>>.
      +<<"ÿÿÿÿÿÿÿÿ">>
      +2> [X || <<X:64/float>> <= <<0.0/float,BadFloat/binary,42.0/float>>].
      +[0.0,42.0]

      Own Id: OTP-19331 Aux Id: PR-8978

    Compiler 8.5.3

    Fixed Bugs and Malfunctions

    • In rare circumstances, the destructive tuple update optimization could be applied when it was unsafe.

      Own Id: OTP-19340 Aux Id: GH-9014, PR-9024

    • In rare circumstances involving appending to multiple binaries, the compile could emit unsafe code that would crash the runtime system.

      Own Id: OTP-19374 Aux Id: GH-9100, PR-9111

    Compiler 8.5.2

    Fixed Bugs and Malfunctions

    • Fixed a crash in an optimization pass relating to appending binaries.

      Own Id: OTP-19168 Aux Id: GH-8630

    • Fixed a bug in the compiler's alias analysis pass that could make it emit unsafe code.

      Own Id: OTP-19178 Aux Id: PR-8686

    Compiler 8.5.1

    Fixed Bugs and Malfunctions

    • One of the compiler's optimization passes would get very slow when compiling certain modules. The compiler will now automatically disable that pass for input that would trigger the slowdown.

      Own Id: OTP-19131 Aux Id: PR-8567

    • Fix +deterministic to work properly with documentation attributes.

      Own Id: OTP-19142 Aux Id: PR-8585, GH-8579

    Compiler 8.5

    Fixed Bugs and Malfunctions

    • Generators for binary comprehensions could be evaluated before it was known that they would be needed. That could result in a binary comprehensions failing if a generator that should not be evaluated until later failed.

      As an example, consider this module:

      -module(t).
      +-export([f/0]).
       
      -f() ->
      -    <<0 || _ <- [], _ <- ok, false>>.

      In Erlang/OTP 26 it would fail like so:

      1> t:f().
      +f() ->
      +    <<0 || _ <- [], _ <- ok, false>>.

      In Erlang/OTP 26 it would fail like so:

      1> t:f().
       ** exception error: bad generator ok
      -     in function  t:f/0 (t.erl, line 6)

      In Erlang/OTP 27 it returns an empty binary:

      1> t:f().
      -<<>>

      Own Id: OTP-18703 Aux Id: GH-7494, PR-7538

    • The documentation for the preprocessor now mentions that defined(Name) can be called in the condition for an -if or -elif directive to test whether Name is the name of a defined macro. (This feature was implemented in OTP 21.)

      If a function call in an -if or -elif with a name that is not the name of a guard BIF, there would not be a compilation error, but would instead cause the lines following the directive to be skipped. This has now been changed to be a compilation error.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-18784 Aux Id: GH-7706, PR-7726

    Improvements and New Features

    • The compiler now emits nicer error message for function head mismatches. -For example, given:

      a() -> ok;
      -a(_) -> error.

      Erlang/OTP 26 and earlier would emit a diagnostic similar to:

      t.erl:6:1: head mismatch
      +     in function  t:f/0 (t.erl, line 6)

      In Erlang/OTP 27 it returns an empty binary:

      1> t:f().
      +<<>>

      Own Id: OTP-18703 Aux Id: GH-7494, PR-7538

    • The documentation for the preprocessor now mentions that defined(Name) can be called in the condition for an -if or -elif directive to test whether Name is the name of a defined macro. (This feature was implemented in OTP 21.)

      If a function call in an -if or -elif with a name that is not the name of a guard BIF, there would not be a compilation error, but would instead cause the lines following the directive to be skipped. This has now been changed to be a compilation error.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-18784 Aux Id: GH-7706, PR-7726

    Improvements and New Features

    • The compiler now emits nicer error message for function head mismatches. +For example, given:

      a() -> ok;
      +a(_) -> error.

      Erlang/OTP 26 and earlier would emit a diagnostic similar to:

      t.erl:6:1: head mismatch
       %    6| a(_) -> error.
       %     | ^

      while in Erlang/OTP 27 the diagnostic is similar to:

      t.erl:6:1: head mismatch: function a with arities 0 and 1 is regarded as two distinct functions. Is the number of arguments incorrect or is the semicolon in a/0 unwanted?
       %    6| a(_) -> error.
      -%     | ^

      Own Id: OTP-18648 Aux Id: PR-7383

    • The compiler now optimizes creation of binaries that are known to be constant.

      Consider this example:

      bin() ->
      -    C = char(),
      -    <<C>>.
      -
      -char() -> $*.

      Essentially, the compiler rewrites the example to the slightly more efficient:

      bin() ->
      -    _ = char(),
      -    <<$*>>.
      -
      -char() -> $*.

      Own Id: OTP-18673 Aux Id: PR-7474, ERIERL-964

    • The compiler will now merge consecutive updates of the same record.

      As an example, the body of the following function will be combined into a single tuple creation instruction:

      -record(r, {a,b,c,d}).
      -
      -update(Value) ->
      -    R0 = #r{},
      -    R1 = R0#r{a=Value},
      -    R2 = R1#r{b=2},
      -    R2#r{c=3}.

      Own Id: OTP-18680 Aux Id: PR-7491, PR-8086, ERIERL-967

    • Improved the performance of the alias analysis pass.

      Own Id: OTP-18714 Aux Id: PR-7528, GH-7432

    • -spec attributes are now used for documentation.

      Own Id: OTP-18801 Aux Id: PR-7739

    • Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code.

      There are also new APIs to support native coverage without using the cover tool.

      To instrument code for native coverage it must be compiled with the line_coverage option.

      To enable native coverage in the runtime system, start it like so:

      $ erl +JPcover true

      There are also the following new functions for supporting native coverage:

      Own Id: OTP-18856 Aux Id: PR-7856

    • EEP-59 - Documentation Attributes has been implemented.

      Documentation attributes can be used to document functions, types, callbacks, and modules. +% | ^

  • Own Id: OTP-18648 Aux Id: PR-7383

  • The compiler now optimizes creation of binaries that are known to be constant.

    Consider this example:

    bin() ->
    +    C = char(),
    +    <<C>>.
    +
    +char() -> $*.

    Essentially, the compiler rewrites the example to the slightly more efficient:

    bin() ->
    +    _ = char(),
    +    <<$*>>.
    +
    +char() -> $*.

    Own Id: OTP-18673 Aux Id: PR-7474, ERIERL-964

  • The compiler will now merge consecutive updates of the same record.

    As an example, the body of the following function will be combined into a single tuple creation instruction:

    -record(r, {a,b,c,d}).
    +
    +update(Value) ->
    +    R0 = #r{},
    +    R1 = R0#r{a=Value},
    +    R2 = R1#r{b=2},
    +    R2#r{c=3}.

    Own Id: OTP-18680 Aux Id: PR-7491, PR-8086, ERIERL-967

  • Improved the performance of the alias analysis pass.

    Own Id: OTP-18714 Aux Id: PR-7528, GH-7432

  • -spec attributes are now used for documentation.

    Own Id: OTP-18801 Aux Id: PR-7739

  • Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code.

    There are also new APIs to support native coverage without using the cover tool.

    To instrument code for native coverage it must be compiled with the line_coverage option.

    To enable native coverage in the runtime system, start it like so:

    $ erl +JPcover true

    There are also the following new functions for supporting native coverage:

    Own Id: OTP-18856 Aux Id: PR-7856

  • EEP-59 - Documentation Attributes has been implemented.

    Documentation attributes can be used to document functions, types, callbacks, and modules. The keyword -moduledoc "Documentation here". is used to document modules, while -doc "Documentation here". can be used on top of functions, types, and callbacks to document them, respectively.

    • Types, callbacks, and function documentation can be set to hidden either via -doc false or -doc hidden. When documentation attributes mark a type as hidden, they will not be part of the documentation.

    • The documentation from moduledoc and doc gets added by default to the binary beam file, following the format of EEP-48.

    • Using the compiler flag warn_missing_doc will raise a warning when -doc attributes are missing in exported functions, types, and callbacks.

    • Using the compiler flag warn_missing_spec_documented will raise a warning when -spec attributes are missing in documented functions, types, and callbacks.

    • moduledocs and docs may refer to external files to be embedded, such as -doc {file, "README.md"}., which refers to the file README.md found in the current working directory.

    • The compiler warns about exported functions whose specs refer to hidden types. Thus, there will be warnings when a hidden type (meaning, the type is not part of the documentation) gets used in an exported function.

    Own Id: OTP-18916 Aux Id: PR-7936

  • The documentation has been migrated to use Markdown and ExDoc.

    Own Id: OTP-18955 Aux Id: PR-8026

  • The order in which the compiler looks up options has changed.

    When there is a conflict in the compiler options given in the -compile() attribute and options given to the compiler, the options given in the -compile() attribute overrides the option given to the compiler, which in turn overrides options given in the ERL_COMPILER_OPTIONS environment variable.

    Example:

    If some_module.erl has the following attribute:

    -compile([nowarn_missing_spec]).

    and the compiler is invoked like so:

    % erlc +warn_missing_spec some_module.erl

    no warnings will be issued for functions that do not have any specs.

    POTENTIAL INCOMPATIBILITY

    Own Id: OTP-18968 Aux Id: GH-6979, PR-8093

  • Safe destructive update of tuples has been implemented in the compiler and runtime system. This allows the VM to update tuples in-place when it is safe to do so, thus improving performance by doing less copying but also by producing less garbage.

    Example:

    -record(rec, {a,b,c}).
    +spec attributes are missing in documented functions, types, and callbacks.

  • moduledocs and docs may refer to external files to be embedded, such as -doc {file, "README.md"}., which refers to the file README.md found in the current working directory.

  • The compiler warns about exported functions whose specs refer to hidden types. Thus, there will be warnings when a hidden type (meaning, the type is not part of the documentation) gets used in an exported function.

  • Own Id: OTP-18916 Aux Id: PR-7936

  • The documentation has been migrated to use Markdown and ExDoc.

    Own Id: OTP-18955 Aux Id: PR-8026

  • The order in which the compiler looks up options has changed.

    When there is a conflict in the compiler options given in the -compile() attribute and options given to the compiler, the options given in the -compile() attribute overrides the option given to the compiler, which in turn overrides options given in the ERL_COMPILER_OPTIONS environment variable.

    Example:

    If some_module.erl has the following attribute:

    -compile([nowarn_missing_spec]).

    and the compiler is invoked like so:

    % erlc +warn_missing_spec some_module.erl

    no warnings will be issued for functions that do not have any specs.

    POTENTIAL INCOMPATIBILITY

    Own Id: OTP-18968 Aux Id: GH-6979, PR-8093

  • Safe destructive update of tuples has been implemented in the compiler and runtime system. This allows the VM to update tuples in-place when it is safe to do so, thus improving performance by doing less copying but also by producing less garbage.

    Example:

    -record(rec, {a,b,c}).
     
    -update(#rec{a=needs_update,b=N}=R0) ->
    -    R = R0#rec{a=up_to_date},
    +update(#rec{a=needs_update,b=N}=R0) ->
    +    R = R0#rec{a=up_to_date},
         if
             N < 0 ->
    -            R#rec{c=negative};
    +            R#rec{c=negative};
             N == 0 ->
    -            R#rec{c=zero};
    +            R#rec{c=zero};
             N > 0 ->
    -            R#rec{c=positive}
    +            R#rec{c=positive}
         end.

    The record updates in each of the three clauses of the if can safely be done in-place, because variable R is not used again.

    Own Id: OTP-18972 Aux Id: PR-8090

  • Improved the match context reuse optimization slightly, allowing match contexts to be passed as-is to bit_size/1 and byte_size/1.

    Own Id: OTP-18987

  • erl_lint (and by extension the compiler) will now warn for code using deprecated callbacks.

    The only callback currenly deprecated is format_status/2 in gen_server, gen_event and gen_statem.

    You can use nowarn_deprecated_callback to silence the warning.

    Own Id: OTP-19010 Aux Id: PR-8205

  • Compiler 8.4.3.4

    Fixed Bugs and Malfunctions

    • Fixed broken type inference for lists:mapfoldl/r.

      Own Id: OTP-19845 Aux Id: GH-10354, PR-10358

    Compiler 8.4.3.3

    Fixed Bugs and Malfunctions

    • Fix a bug where unloaded nifs can crash the compiler.

      Own Id: OTP-19600 Aux Id: PR-9737, GH-9715

    Compiler 8.4.3.2

    Fixed Bugs and Malfunctions

    • Fixed a bug where bogus code was generated for consecutive calls to erlang:setelement/2, potentially crashing the emulator.

      Own Id: OTP-19270 Aux Id: GH-8783 PR-8898

    Compiler 8.4.3.1

    Fixed Bugs and Malfunctions

    • Fixed a crash in an optimization pass relating to appending binaries.

      Own Id: OTP-19168 Aux Id: GH-8630

    • Fixed a bug in the compiler's alias analysis pass that could make it emit unsafe code.

      Own Id: OTP-19178 Aux Id: PR-8686

    Compiler 8.4.3

    Fixed Bugs and Malfunctions

    • In rare circumstances, the compiler code generate unsafe code for a bit syntax match.

      Own Id: OTP-19019

    • In rare circumstances, binary matches that were supposed to succeed failed.

      Own Id: OTP-19035 Aux Id: GH-8280, PR-8284

    • Fixed a bug where a fun's environment could be overridden by an argument if all of the following conditions were met:

      • The fun was declared in the module that called it.
      • The fun's target was statically known.
      • The fun was called with a number of extra arguments equal to the number of environment variables.

      Own Id: OTP-19045 Aux Id: GH-8316

    Compiler 8.4.2

    Fixed Bugs and Malfunctions

    • In rare circumstances, an unsafe optimization could cause the compiler to generate incorrect code for list matching.

      Own Id: OTP-19003 Aux Id: GH-8187, PR-8189

    Improvements and New Features

    • Fix the compilation server to restart if the applications in its lib dir changes inbetween erlc invokations.

      Own Id: OTP-18936

    Compiler 8.4.1

    Fixed Bugs and Malfunctions

    • The compiler could become extremely slow for modules containing huge functions.

      Own Id: OTP-18770 Aux Id: GH-7667, PR-7672

    Compiler 8.4

    Fixed Bugs and Malfunctions

    • The compiler could run forever when compiling a call to is_record/3 with a huge positive tuple size. The call /usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/ssa_checks.xhtml differs (HTML document, ASCII text, with very long lines (1093)) --- old//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/ssa_checks.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/compiler.epub/OEBPS/ssa_checks.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -28,32 +28,32 @@ functionality.

      Syntax

      SSA checks are embedded in the source code as comments starting with with one of %ssa%, %%ssa% or %%%ssa%. This is a short introduction the syntax, for the full syntax please refer to the -ssa_check_when_clause production in erl_parse.yrl.

      SSA checks can be placed inside any Erlang function, for example:

      t0() ->
      +ssa_check_when_clause production in erl_parse.yrl.

      SSA checks can be placed inside any Erlang function, for example:

      t0() ->
       %ssa% () when post_ssa_opt ->
       %ssa%   ret(#{}).
      -  #{}.

      will check that t0/0 returns the literal #{}. If we want to check -that a function returns its first formal parameter, we can write:

      t1(A, _B) ->
      +  #{}.

      will check that t0/0 returns the literal #{}. If we want to check +that a function returns its first formal parameter, we can write:

      t1(A, _B) ->
       %ssa% (X, _) when post_ssa_opt ->
       %ssa%   ret(X).
         A.

      Note how we match the first formal parameter using X. The reason for having our own formal parameters for the SSA check, is that we don't want to introduce new identifiers at the Erlang level to support SSA-level checks. Consider if t1/2 had been defined as t1([A|As], B) we would have had to introduce a new identifier for the aggregate -value [A|As].

      The full syntax for a SSA check clause is:

      <expected-result>? (<formals>) when <pipeline-location> -> <checks> '.'

      where <expected-result> can be one of pass (the check must +value [A|As].

      The full syntax for a SSA check clause is:

      <expected-result>? (<formals>) when <pipeline-location> -> <checks> '.'

      where <expected-result> can be one of pass (the check must succeed), fail and xfail (the check must fail). Omitting <expected-result> is parsed as an implicit pass.

      <formals> is a comma-separated list of variables.

      <pipeline-location> specifies when in the compiler pipeline to run the checks. For now the only supported value for <pipeline-location> is post_ssa_opt which runs the checks after the ssa_opt pass.

      <checks> is a comma-separated list of matches against the BEAM SSA -code. For non-flow-control operations the syntax is:

      <variable> = <operation> ( <arguments> ) <annotation>?

      where <operation> is the #b_set.op field from the internal SSA -representation. BIFs are written as bif:<atom>.

      <arguments> is a comma-separated list of variables or literals.

      For flow control operations and labels, the syntax is as follows:

      br(<bool>, <true-label>, <false-label>)
      +code. For non-flow-control operations the syntax is:

      <variable> = <operation> ( <arguments> ) <annotation>?

      where <operation> is the #b_set.op field from the internal SSA +representation. BIFs are written as bif:<atom>.

      <arguments> is a comma-separated list of variables or literals.

      For flow control operations and labels, the syntax is as follows:

      br(<bool>, <true-label>, <false-label>)
       
      -switch(<value>, <fail-label>, [{<label>,<value>},...])
      +switch(<value>, <fail-label>, [{<label>,<value>},...])
       
      -ret(<value>)
      +ret(<value>)
       
       label <value>

      where <value> is a literal or a variable.

      A check can also include an assertion on operation annotations. The assertion is written as a map-like pattern following the argument -list, for example:

      t0() ->
      +list, for example:

      t0() ->
       %ssa% () when post_ssa_opt ->
       %ssa% _ = call(fun return_int/0) { result_type => {t_integer,{17,17}},
       %ssa%                              location => {_,32} },
      @@ -61,9 +61,9 @@
       %ssa%    result_type => {t_tuple,2,true,#{1 => {t_integer,{1,1}},
       %ssa%                                     2 => {t_integer,{2,2}}}}
       %ssa% }.
      -    X = return_int(),
      -    Y = return_tuple(),
      -    {X, Y}.

      Semantics

      When an SSA assertion is matched against the BEAM SSA for a function, + X = return_int(), + Y = return_tuple(), + {X, Y}.

      Semantics

      When an SSA assertion is matched against the BEAM SSA for a function, patterns are applied sequentially. If the current pattern doesn't match, the checker tries with the next instruction. If the checker reaches the end of the SSA representation without having matched all /usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (10983)) --- old//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/notes.html 2026-08-21 04:00:19.813297300 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/notes.html 2026-08-21 04:00:19.813297300 +0000 @@ -89,48 +89,48 @@ -

      This document describes the changes made to the Compiler application.

      Compiler 9.0.6.1

      Fixed Bugs and Malfunctions

      • In rare circumstances, optimization of boolean expressions could invert the boolean value.

        Own Id: OTP-20140 Aux Id: GH-11088, PR-11089

      Compiler 9.0.6

      Fixed Bugs and Malfunctions

      • The type inference for maps:from_list/1 was incorrect: when the provided list was statically known to be bogus when non-empty (e.g. a list of atoms), the compiler assumed it would also fail when the list was empty.

        Own Id: OTP-19506 Aux Id: GH-9476, PR-9481

      • Fixed a bug in the type analysis pass that could erroneously eliminate code blocks.

        Own Id: OTP-19931 Aux Id: GH-10562, PR-10569

      • A binary as the value of a -moduledoc() attribute would be silently ignored.

        Own Id: OTP-20065 Aux Id: GH-10901, PR-10904

      Compiler 9.0.5

      Fixed Bugs and Malfunctions

      • Fixed a compiler alias analysis bug that could generate unsafe code for repeated binary segments.

        Own Id: OTP-19951 Aux Id: PR-10588

      Compiler 9.0.4

      Fixed Bugs and Malfunctions

      • For some function heads or case expressions with a huge number of clauses, the compiler could spend an inordinate amount of time compiling the code.

        Own Id: OTP-19797 Aux Id: PR-10252

      • Passing a type for a fun as a macro argument would result in a "badly formed argument" error message from the compiler. Example:

        -module(test).
        --define(FOO(X), X).
        --type foo() :: ?FOO(fun(() -> ok)).

        Compiling this module would result in the following error message:

        test.erl:3:17: badly formed argument for macro &#href_anchor"w">
        +

        This document describes the changes made to the Compiler application.

        Compiler 9.0.6.1

        Fixed Bugs and Malfunctions

        • In rare circumstances, optimization of boolean expressions could invert the boolean value.

          Own Id: OTP-20140 Aux Id: GH-11088, PR-11089

        Compiler 9.0.6

        Fixed Bugs and Malfunctions

        • The type inference for maps:from_list/1 was incorrect: when the provided list was statically known to be bogus when non-empty (e.g. a list of atoms), the compiler assumed it would also fail when the list was empty.

          Own Id: OTP-19506 Aux Id: GH-9476, PR-9481

        • Fixed a bug in the type analysis pass that could erroneously eliminate code blocks.

          Own Id: OTP-19931 Aux Id: GH-10562, PR-10569

        • A binary as the value of a -moduledoc() attribute would be silently ignored.

          Own Id: OTP-20065 Aux Id: GH-10901, PR-10904

        Compiler 9.0.5

        Fixed Bugs and Malfunctions

        • Fixed a compiler alias analysis bug that could generate unsafe code for repeated binary segments.

          Own Id: OTP-19951 Aux Id: PR-10588

        Compiler 9.0.4

        Fixed Bugs and Malfunctions

        • For some function heads or case expressions with a huge number of clauses, the compiler could spend an inordinate amount of time compiling the code.

          Own Id: OTP-19797 Aux Id: PR-10252

        • Passing a type for a fun as a macro argument would result in a "badly formed argument" error message from the compiler. Example:

          -module(test).
          +-define(FOO(X), X).
          +-type foo() :: ?FOO(fun(() -> ok)).

          Compiling this module would result in the following error message:

          test.erl:3:17: badly formed argument for macro &#href_anchor"w">
           %    5| -type foo() :: ?FOO(fun(() -> ok)).
          -%

          Own Id: OTP-19821 Aux Id: GH-10280, PR-10309

        • In certain edge cases, the compiler could emit code that would do an unsafe destructive update of a tuple. This has been corrected.

          Own Id: OTP-19879 Aux Id: GH-10367, PR-10435

        Improvements and New Features

        • The compiler option beam_debug_stack combined with beam_debug_info will attempt to make as many variables as possible visible in the debugger. The option has no effect if given without beam_debug_info.

          Own Id: OTP-19854 Aux Id: PR-10374

        Compiler 9.0.3

        Fixed Bugs and Malfunctions

        • Fixed broken type inference for lists:mapfoldl/r.

          Own Id: OTP-19845 Aux Id: GH-10354, PR-10358

        Compiler 9.0.2

        Fixed Bugs and Malfunctions

        • Fixed a compiler crash caused by patch order in destructive update.

          Own Id: OTP-19660 Aux Id: GH-9903, PR-9909

        • Fixed a compiler crash in beam_ssa_pre_codegen caused by wrong handling of multiple phi patches in the destructive update pass.

          Own Id: OTP-19689 Aux Id: GH-9987, PR-9990

        • Fixed a crash when a zip generator contains a map pattern.

          Own Id: OTP-19693 Aux Id: PR-10009, GH-10002

        • In rare circumstances, the compiler could crash when compiling code using bit syntax construction.

          Own Id: OTP-19722 Aux Id: GH-10077, PR-10090

        • A few minor bugs that could affect the beam_debug_info option were fixed.

          Own Id: OTP-19758 Aux Id: PR-10153

        Compiler 9.0.1

        Fixed Bugs and Malfunctions

        • Fixed a bug that could cause empty bitstring matches to always succeed, even when they should not.

          Own Id: OTP-19711 Aux Id: GH-10047, PR-10048

        Compiler 9.0

        Fixed Bugs and Malfunctions

        • The compiler will now emit warnings when some map patterns cannot possibly match because a previous clauses matches the same pattern. For example:

          mm_1(#{}) -> a;
          -mm_1(#{b := B}) -> {b,B}.
          +%

          Own Id: OTP-19821 Aux Id: GH-10280, PR-10309

        • In certain edge cases, the compiler could emit code that would do an unsafe destructive update of a tuple. This has been corrected.

          Own Id: OTP-19879 Aux Id: GH-10367, PR-10435

        Improvements and New Features

        • The compiler option beam_debug_stack combined with beam_debug_info will attempt to make as many variables as possible visible in the debugger. The option has no effect if given without beam_debug_info.

          Own Id: OTP-19854 Aux Id: PR-10374

        Compiler 9.0.3

        Fixed Bugs and Malfunctions

        • Fixed broken type inference for lists:mapfoldl/r.

          Own Id: OTP-19845 Aux Id: GH-10354, PR-10358

        Compiler 9.0.2

        Fixed Bugs and Malfunctions

        • Fixed a compiler crash caused by patch order in destructive update.

          Own Id: OTP-19660 Aux Id: GH-9903, PR-9909

        • Fixed a compiler crash in beam_ssa_pre_codegen caused by wrong handling of multiple phi patches in the destructive update pass.

          Own Id: OTP-19689 Aux Id: GH-9987, PR-9990

        • Fixed a crash when a zip generator contains a map pattern.

          Own Id: OTP-19693 Aux Id: PR-10009, GH-10002

        • In rare circumstances, the compiler could crash when compiling code using bit syntax construction.

          Own Id: OTP-19722 Aux Id: GH-10077, PR-10090

        • A few minor bugs that could affect the beam_debug_info option were fixed.

          Own Id: OTP-19758 Aux Id: PR-10153

        Compiler 9.0.1

        Fixed Bugs and Malfunctions

        • Fixed a bug that could cause empty bitstring matches to always succeed, even when they should not.

          Own Id: OTP-19711 Aux Id: GH-10047, PR-10048

        Compiler 9.0

        Fixed Bugs and Malfunctions

        • The compiler will now emit warnings when some map patterns cannot possibly match because a previous clauses matches the same pattern. For example:

          mm_1(#{}) -> a;
          +mm_1(#{b := B}) -> {b,B}.
           
          -mm_2(#{a := A}) -> {a,A};
          -mm_2(#{a := A, b := B}) -> {b,A,B}.

          The second clause of these function can never match and the compiler will now emit a warning for both of them.

          Note that the compiler is not guaranteed to emit warnings for every possible map pattern that cannot match.

          Own Id: OTP-19141 Aux Id: GH-8558, PR-8600

        • The size of an atom in the Erlang source code was limited to 255 bytes in previous releases, meaning that an atom containing only emojis could contain only 63 emojis.

          While atoms are still only allowed to contain 255 characters, the number of bytes is no longer limited.

          External tools that parse the AtU8 chunk of a BEAM file directly need to be updated. Tools that use beam_lib:chunks(Beam, [atoms]) to read the atom table will continue to work.

          POTENTIAL INCOMPATIBILITY

          Own Id: OTP-19285 Aux Id: PR-8913

        • The literals chunk in BEAM is no longer compressed, resulting in slightly smaller BEAM files when a BEAM file is stripped using beam_lib:strip_files/1.

          This is a potential incompatibility for tools that read and interpret the contents of the literal chunk. One way to update such tools to work with the new format is to retrieve the chunk using beam_lib:chunks(Beam, [literals]).

          POTENTIAL INCOMPATIBILITY

          Own Id: OTP-19323 Aux Id: GH-8967, PR-8988

        • The final validation step in the compiler will now reject modules containing functions with more than 255 arguments. No impact is expected as the emulator has always refused to load these modules.

          Own Id: OTP-19376 Aux Id: GH-9113, PR-9121

        • Replaced calls to deprecated crypto:start() with application:start(crypto).

          Own Id: OTP-19485 Aux Id: PR-8592

        • Refactor code to not rely on +nowarn_shadow_vars.

          Own Id: OTP-19574 Aux Id: PR-9678

        Improvements and New Features

        • The EEP-48 doc chunk embedded into .beam files by the compiler is now compressed and deterministic.

          Own Id: OTP-19096 Aux Id: PR-8494

        • Provided that the map argument for a maps:put/3 call is known to the compiler to be a map, the compiler will replace such calls with the corresponding update using the map syntax.

          Own Id: OTP-19115 Aux Id: PR-8540

        • For various error types, the compiler now tries to suggest potential fixes by adding "did you mean ...?" at the end of error messages.

          When a function is used with wrong arity, the compiler will try to suggest a defined function with the same name but a different arity. For example, given the following module:

          -module(typos).
          --export([t/0]).
          -bar(A) -> A.
          -bar(A,A,A) -> A.
          -bar(A,A,A,A) -> A.
          -t() -> bar(0, 0).

          The compiler will emit the following message:

          typo.erl:6:12: function bar/2 undefined, did you mean bar/1,3,4?
          +mm_2(#{a := A}) -> {a,A};
          +mm_2(#{a := A, b := B}) -> {b,A,B}.

          The second clause of these function can never match and the compiler will now emit a warning for both of them.

          Note that the compiler is not guaranteed to emit warnings for every possible map pattern that cannot match.

          Own Id: OTP-19141 Aux Id: GH-8558, PR-8600

        • The size of an atom in the Erlang source code was limited to 255 bytes in previous releases, meaning that an atom containing only emojis could contain only 63 emojis.

          While atoms are still only allowed to contain 255 characters, the number of bytes is no longer limited.

          External tools that parse the AtU8 chunk of a BEAM file directly need to be updated. Tools that use beam_lib:chunks(Beam, [atoms]) to read the atom table will continue to work.

          POTENTIAL INCOMPATIBILITY

          Own Id: OTP-19285 Aux Id: PR-8913

        • The literals chunk in BEAM is no longer compressed, resulting in slightly smaller BEAM files when a BEAM file is stripped using beam_lib:strip_files/1.

          This is a potential incompatibility for tools that read and interpret the contents of the literal chunk. One way to update such tools to work with the new format is to retrieve the chunk using beam_lib:chunks(Beam, [literals]).

          POTENTIAL INCOMPATIBILITY

          Own Id: OTP-19323 Aux Id: GH-8967, PR-8988

        • The final validation step in the compiler will now reject modules containing functions with more than 255 arguments. No impact is expected as the emulator has always refused to load these modules.

          Own Id: OTP-19376 Aux Id: GH-9113, PR-9121

        • Replaced calls to deprecated crypto:start() with application:start(crypto).

          Own Id: OTP-19485 Aux Id: PR-8592

        • Refactor code to not rely on +nowarn_shadow_vars.

          Own Id: OTP-19574 Aux Id: PR-9678

        Improvements and New Features

        • The EEP-48 doc chunk embedded into .beam files by the compiler is now compressed and deterministic.

          Own Id: OTP-19096 Aux Id: PR-8494

        • Provided that the map argument for a maps:put/3 call is known to the compiler to be a map, the compiler will replace such calls with the corresponding update using the map syntax.

          Own Id: OTP-19115 Aux Id: PR-8540

        • For various error types, the compiler now tries to suggest potential fixes by adding "did you mean ...?" at the end of error messages.

          When a function is used with wrong arity, the compiler will try to suggest a defined function with the same name but a different arity. For example, given the following module:

          -module(typos).
          +-export([t/0]).
          +bar(A) -> A.
          +bar(A,A,A) -> A.
          +bar(A,A,A,A) -> A.
          +t() -> bar(0, 0).

          The compiler will emit the following message:

          typo.erl:6:12: function bar/2 undefined, did you mean bar/1,3,4?
           %   6|     t() -> bar(0, 0).
          -%    |            ^

          For compiler errors that can easily be caused by typos, the compiler will try to suggest what the correct variable or function name, could be. For example, given the following module:

          -module(typos).
          --export([bar/2]).
          +%    |            ^

          For compiler errors that can easily be caused by typos, the compiler will try to suggest what the correct variable or function name, could be. For example, given the following module:

          -module(typos).
          +-export([bar/2]).
           
          -bar(A0, B0) ->
          +bar(A0, B0) ->
               A + B.

          the compiler will emit the following error messages:

          typos.erl:5:5: variable &#href_anchor"w"> is unbound, did you mean 'A0'?
           %    5|     A + B.
           %     |     ^
           
           typos.erl:5:9: variable 'B' is unbound, did you mean 'B0'?
           %    5|     A + B.
          -%     |         ^

          Error types that now suggest correct arities: bad_inline, undefined_nif, bad_nowarn_unused_function, bad_nowarn_bif_clash, undefined_function.

          Error types that now suggest correct names: bad_inline, undefined_nif, bad_nowarn_unused_function, undefined_on_load, undefined_function, undefined_record, undefined_field, unbound_var.

          Using a function with wrong arity has higher precedence than having a typo in the function name. If the compiler can find a defined function with the same name but a different arity, it will not suggest a defined function with a close-enough name, regardless of arity.

          Own Id: OTP-19180 Aux Id: PR-8699, PR-9094

        • Comprehensions have been extended with zip generators according to EEP 73.

          Example:

          1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
          -[5,7,9]

          Own Id: OTP-19184 Aux Id: PR-8926

        • Documentation chunks (EEP-48) has been updated to include the following reserved metadata fields: behaviours, group, source_path, and source_annos. The compiler has also been updated to emit this metadata. See the EEP-48 documentation for more details.

          Own Id: OTP-19306 Aux Id: PR-8945, PR-8975

        • New strict generators have been added for comprehensions.

          The currently existing generators are "relaxed": they ignore terms in the +% | ^

        Error types that now suggest correct arities: bad_inline, undefined_nif, bad_nowarn_unused_function, bad_nowarn_bif_clash, undefined_function.

        Error types that now suggest correct names: bad_inline, undefined_nif, bad_nowarn_unused_function, undefined_on_load, undefined_function, undefined_record, undefined_field, unbound_var.

        Using a function with wrong arity has higher precedence than having a typo in the function name. If the compiler can find a defined function with the same name but a different arity, it will not suggest a defined function with a close-enough name, regardless of arity.

        Own Id: OTP-19180 Aux Id: PR-8699, PR-9094

      • Comprehensions have been extended with zip generators according to EEP 73.

        Example:

        1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
        +[5,7,9]

        Own Id: OTP-19184 Aux Id: PR-8926

      • Documentation chunks (EEP-48) has been updated to include the following reserved metadata fields: behaviours, group, source_path, and source_annos. The compiler has also been updated to emit this metadata. See the EEP-48 documentation for more details.

        Own Id: OTP-19306 Aux Id: PR-8945, PR-8975

      • New strict generators have been added for comprehensions.

        The currently existing generators are "relaxed": they ignore terms in the right-hand side expression that do not match the left-hand side pattern.

        The new strict generators fail with exception badmatch if a pattern doesn't match.

        Examples:

        Using the current relaxed generator operator <-, any element not matching -the pattern {_,_} will be silently discarded:

        1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
        -[{ok,1},{error,2}]

        If the intention is that all lists processed by a list comprehension must only +the pattern {_,_} will be silently discarded:

        1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
        +[{ok,1},{error,2}]

        If the intention is that all lists processed by a list comprehension must only contain tuples of size two, using the new strict version of the operator ensures -that term not matching will cause a crash:

        2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
        +that term not matching will cause a crash:

        2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
         ** exception error: no match of right hand side value ok

        Using the strict generator operator to mark the intention that all list elements must match the pattern could help finding mistakes quicker if something unpexected is added to the list processed by the generator.

        The strict version for bitstring generators is <:=.

        Own Id: OTP-19317 Aux Id: PR-8625

      • New options for suppressing behaviour warnings have been added:

        • nowarn_conflicting_behaviours
        • nowarn_undefined_behaviour_func
        • nowarn_undefined_behaviour
        • nowarn_undefined_behaviour_callbacks
        • nowarn_ill_defined_behaviour_callbacks
        • nowarn_ill_defined_optional_callbacks

        Own Id: OTP-19334 Aux Id: GH-8985, PR-9020

      • Some BIFs with side-effects are optimized in try/catch in the same way as guard BIFs in order to gain performance.

        The following BIFs that are optimized in this way: binary_to_atom/1, binary_to_atom/2, binary_to_existing_atom/1, list_to_atom/1, and -list_to_existing_atom/1.

        Own Id: OTP-19339 Aux Id: PR-9042, PR-9122

      • The compiler now converts known documentation attribute metadata entries from unicode:chardata/0 to unicode:unicode_binary/0.

        Own Id: OTP-19394 Aux Id: PR-9192

      • The warn_deprecated_catch option enables warnings for use of old-style catch expressions on the form catch Expr instead of the modern try ... catch ... end. To prevent new uses of uses of old catches to be added, this compiler option can be enabled on the project level and -compile(nowarn_deprecated_catch). added to individual files that still contain old catches.

        Own Id: OTP-19425 Aux Id: PR-9154

      • Defining a fun in terms of an imported function is not allowed. Before this release, the compiler would not catch this kind of error if the name of the imported function happened to be a BIF. Consider this example:

        -module(fun_example).
        --export([foo/0, bar/0]).
        --import(m, [max/2, not_a_bif/0]).
        +list_to_existing_atom/1.

        Own Id: OTP-19339 Aux Id: PR-9042, PR-9122

      • The compiler now converts known documentation attribute metadata entries from unicode:chardata/0 to unicode:unicode_binary/0.

        Own Id: OTP-19394 Aux Id: PR-9192

      • The warn_deprecated_catch option enables warnings for use of old-style catch expressions on the form catch Expr instead of the modern try ... catch ... end. To prevent new uses of uses of old catches to be added, this compiler option can be enabled on the project level and -compile(nowarn_deprecated_catch). added to individual files that still contain old catches.

        Own Id: OTP-19425 Aux Id: PR-9154

      • Defining a fun in terms of an imported function is not allowed. Before this release, the compiler would not catch this kind of error if the name of the imported function happened to be a BIF. Consider this example:

        -module(fun_example).
        +-export([foo/0, bar/0]).
        +-import(m, [max/2, not_a_bif/0]).
         
        -foo() ->
        +foo() ->
             fun max/2.
         
        -bar() ->
        +bar() ->
             fun not_a_bif/0.

        The compiler in Erlang/OTP 27 would generate the following messages:

        fun_example.erl:9:5: function not_a_bif/0 undefined
         %    9|     fun not_a_bif/0.
         %     |     ^
        @@ -149,60 +149,60 @@
         fun_example.erl:3:2: Warning: import directive overrides auto-imported BIF max/2 --
         use "-compile({no_auto_import,[max/2]})." to resolve name clash
         %    3| -import(m, [max/2, not_a_bif/0]).
        -%     |  ^

        Also, attempting to call a local function having the same name as auto-imported BIF would result in an error if the BIF was added to Erlang/OTP before R14, and a warning for newer BIFs. This has been changed to always emit a warning. For example:

        -module(bif_example).
        --export([bar/1]).
        +%     |  ^

        Also, attempting to call a local function having the same name as auto-imported BIF would result in an error if the BIF was added to Erlang/OTP before R14, and a warning for newer BIFs. This has been changed to always emit a warning. For example:

        -module(bif_example).
        +-export([bar/1]).
         
        -bar(B) ->
        -    is_boolean(B).
        +bar(B) ->
        +    is_boolean(B).
         
        -is_boolean(B) ->
        +is_boolean(B) ->
                 B =:= true orelse B =:= false.

        will now result in the following warning instead of an error:

        if_example.erl:5:5: Warning: ambiguous call of overridden auto-imported BIF is_boolean/1 --
         use erlang:is_boolean/1 or "-compile({no_auto_import,[is_boolean/1]})." to resolve name clash
         %    5|     is_boolean(B).
        -%     |     ^

        Own Id: OTP-19432 Aux Id: PR-9246

      • The compiler’s alias analysis pass is now both faster and less conservative, allowing optimizations of records and binary construction to be applied in more cases.

        Own Id: OTP-19502 Aux Id: PR-8695

      • BEAM files no longer include a Meta chunk if there are no features used. That slightly decreases the size of BEAM files, and it also ensures that m(Module) and beam_lib:md5(Beam) will match for preloaded modules.

        Own Id: OTP-19524 Aux Id: PR-9517

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      • An experimental API for a native debugger has been added. The main components are the following:

        • A new compiler option beam_debug_info for the Erlang compiler. When given, most optimizations are disabled and debug information suitable for the native debugger are added to generated BEAM files.

        • A new +D emulator flag. When given, the VM becomes "debuggable", which means that when modules that been compiled with the beam_debug_info option are loaded, the code is instrumented so that one can enable and disable breakpoints on executable lines.

        • An experimental erl_debugger module with a new debugging API. Essentially, it allows a single, local, process to be registered as the "debugger" process for the node. This process is the one that will receive messages notifying that a process hit a breakpoint. This way, the front-end implementation of a debugger (such as edb from WhatApp) can be decoupled from OTP.

        • The erl_debugger module also exposes new BIFs to inspect X and Y registers of a suspended process. Together with new code-information BIFs, this let's a debugger show the values of variables in scope for a suspended process.

        Own Id: OTP-19609 Aux Id: PR-8670, PR-9334, PR-9604

      Compiler 8.6.1.4

      Fixed Bugs and Malfunctions

      • The type inference for maps:from_list/1 was incorrect: when the provided list was statically known to be bogus when non-empty (e.g. a list of atoms), the compiler assumed it would also fail when the list was empty.

        Own Id: OTP-19506 Aux Id: GH-9476, PR-9481

      • Fixed a bug in the type analysis pass that could erroneously eliminate code blocks.

        Own Id: OTP-19931 Aux Id: GH-10562, PR-10569

      • A binary as the value of a -moduledoc() attribute would be silently ignored.

        Own Id: OTP-20065 Aux Id: GH-10901, PR-10904

      Compiler 8.6.1.3

      Fixed Bugs and Malfunctions

      • Fixed broken type inference for lists:mapfoldl/r.

        Own Id: OTP-19845 Aux Id: GH-10354, PR-10358

      • Fix a compiler alias analysis bug that can generate unsafe code for repeated binary segments.

        Own Id: OTP-19951 Aux Id: PR-10588

      Compiler 8.6.1.2

      Fixed Bugs and Malfunctions

      • In rare circumstances, the compiler could crash when compiling code using bit syntax construction.

        Own Id: OTP-19722 Aux Id: GH-10077, PR-10090

      Compiler 8.6.1.1

      Fixed Bugs and Malfunctions

      • Fixed a bug that could cause empty bitstring matches to always succeed, even when they should not.

        Own Id: OTP-19711 Aux Id: GH-10047, PR-10048

      Compiler 8.6.1

      Fixed Bugs and Malfunctions

      • Fix the compiler crash when the inner-most tuple in a nested tuple with 3 layers is updated.

        Own Id: OTP-19561 Aux Id: ERIERL-1208, ERIERL-1210, PR-9650

      Compiler 8.6

      Improvements and New Features

      • The beam_validator pass in the compiler that validates generated BEAM now does stronger checks for binary syntax matching.

        Own Id: OTP-19449 Aux Id: PR-9338

      Compiler 8.5.5

      Fixed Bugs and Malfunctions

      • Eliminated a bug in the alias analysis pass that could potentially cause unsafe optimizations of binary construction or record updates.

        Own Id: OTP-19455 Aux Id: PR-9356

      Compiler 8.5.4

      Fixed Bugs and Malfunctions

      • Fixed a crash in the common sub-expression elimination pass.

        Own Id: OTP-19243 Aux Id: GH-8818, PR-8838

      • Fixed a bug where bogus code was generated for consecutive calls to erlang:setelement/2, potentially crashing the runtime system.

        Own Id: OTP-19270 Aux Id: GH-8783, PR-8898

      • When the line_coverage option was used, exceptions could show the wrong line for where the exception was raised.

        Own Id: OTP-19282 Aux Id: PR-8907

      • The line_coverage option would be ignored if given in a compile() attribute within a module.

        Own Id: OTP-19309 Aux Id: GH-8942, PR-8970

      • A segment matching a float in a binary generator will now skip any invalid float (such as a NaN) and continue matching the rest of the binary. Before this correction, the comprehension would stop as soon as an invalid float was encountered.

        Example:

        1> BadFloat = <<-1:64>>.
        -<<"ÿÿÿÿÿÿÿÿ">>
        -2> [X || <<X:64/float>> <= <<0.0/float,BadFloat/binary,42.0/float>>].
        -[0.0,42.0]

        Own Id: OTP-19331 Aux Id: PR-8978

      Compiler 8.5.3

      Fixed Bugs and Malfunctions

      • In rare circumstances, the destructive tuple update optimization could be applied when it was unsafe.

        Own Id: OTP-19340 Aux Id: GH-9014, PR-9024

      • In rare circumstances involving appending to multiple binaries, the compile could emit unsafe code that would crash the runtime system.

        Own Id: OTP-19374 Aux Id: GH-9100, PR-9111

      Compiler 8.5.2

      Fixed Bugs and Malfunctions

      • Fixed a crash in an optimization pass relating to appending binaries.

        Own Id: OTP-19168 Aux Id: GH-8630

      • Fixed a bug in the compiler's alias analysis pass that could make it emit unsafe code.

        Own Id: OTP-19178 Aux Id: PR-8686

      Compiler 8.5.1

      Fixed Bugs and Malfunctions

      • One of the compiler's optimization passes would get very slow when compiling certain modules. The compiler will now automatically disable that pass for input that would trigger the slowdown.

        Own Id: OTP-19131 Aux Id: PR-8567

      • Fix +deterministic to work properly with documentation attributes.

        Own Id: OTP-19142 Aux Id: PR-8585, GH-8579

      Compiler 8.5

      Fixed Bugs and Malfunctions

      • Generators for binary comprehensions could be evaluated before it was known that they would be needed. That could result in a binary comprehensions failing if a generator that should not be evaluated until later failed.

        As an example, consider this module:

        -module(t).
        --export([f/0]).
        +%     |     ^

        Own Id: OTP-19432 Aux Id: PR-9246

      • The compiler’s alias analysis pass is now both faster and less conservative, allowing optimizations of records and binary construction to be applied in more cases.

        Own Id: OTP-19502 Aux Id: PR-8695

      • BEAM files no longer include a Meta chunk if there are no features used. That slightly decreases the size of BEAM files, and it also ensures that m(Module) and beam_lib:md5(Beam) will match for preloaded modules.

        Own Id: OTP-19524 Aux Id: PR-9517

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      • An experimental API for a native debugger has been added. The main components are the following:

        • A new compiler option beam_debug_info for the Erlang compiler. When given, most optimizations are disabled and debug information suitable for the native debugger are added to generated BEAM files.

        • A new +D emulator flag. When given, the VM becomes "debuggable", which means that when modules that been compiled with the beam_debug_info option are loaded, the code is instrumented so that one can enable and disable breakpoints on executable lines.

        • An experimental erl_debugger module with a new debugging API. Essentially, it allows a single, local, process to be registered as the "debugger" process for the node. This process is the one that will receive messages notifying that a process hit a breakpoint. This way, the front-end implementation of a debugger (such as edb from WhatApp) can be decoupled from OTP.

        • The erl_debugger module also exposes new BIFs to inspect X and Y registers of a suspended process. Together with new code-information BIFs, this let's a debugger show the values of variables in scope for a suspended process.

        Own Id: OTP-19609 Aux Id: PR-8670, PR-9334, PR-9604

      Compiler 8.6.1.4

      Fixed Bugs and Malfunctions

      • The type inference for maps:from_list/1 was incorrect: when the provided list was statically known to be bogus when non-empty (e.g. a list of atoms), the compiler assumed it would also fail when the list was empty.

        Own Id: OTP-19506 Aux Id: GH-9476, PR-9481

      • Fixed a bug in the type analysis pass that could erroneously eliminate code blocks.

        Own Id: OTP-19931 Aux Id: GH-10562, PR-10569

      • A binary as the value of a -moduledoc() attribute would be silently ignored.

        Own Id: OTP-20065 Aux Id: GH-10901, PR-10904

      Compiler 8.6.1.3

      Fixed Bugs and Malfunctions

      • Fixed broken type inference for lists:mapfoldl/r.

        Own Id: OTP-19845 Aux Id: GH-10354, PR-10358

      • Fix a compiler alias analysis bug that can generate unsafe code for repeated binary segments.

        Own Id: OTP-19951 Aux Id: PR-10588

      Compiler 8.6.1.2

      Fixed Bugs and Malfunctions

      • In rare circumstances, the compiler could crash when compiling code using bit syntax construction.

        Own Id: OTP-19722 Aux Id: GH-10077, PR-10090

      Compiler 8.6.1.1

      Fixed Bugs and Malfunctions

      • Fixed a bug that could cause empty bitstring matches to always succeed, even when they should not.

        Own Id: OTP-19711 Aux Id: GH-10047, PR-10048

      Compiler 8.6.1

      Fixed Bugs and Malfunctions

      • Fix the compiler crash when the inner-most tuple in a nested tuple with 3 layers is updated.

        Own Id: OTP-19561 Aux Id: ERIERL-1208, ERIERL-1210, PR-9650

      Compiler 8.6

      Improvements and New Features

      • The beam_validator pass in the compiler that validates generated BEAM now does stronger checks for binary syntax matching.

        Own Id: OTP-19449 Aux Id: PR-9338

      Compiler 8.5.5

      Fixed Bugs and Malfunctions

      • Eliminated a bug in the alias analysis pass that could potentially cause unsafe optimizations of binary construction or record updates.

        Own Id: OTP-19455 Aux Id: PR-9356

      Compiler 8.5.4

      Fixed Bugs and Malfunctions

      • Fixed a crash in the common sub-expression elimination pass.

        Own Id: OTP-19243 Aux Id: GH-8818, PR-8838

      • Fixed a bug where bogus code was generated for consecutive calls to erlang:setelement/2, potentially crashing the runtime system.

        Own Id: OTP-19270 Aux Id: GH-8783, PR-8898

      • When the line_coverage option was used, exceptions could show the wrong line for where the exception was raised.

        Own Id: OTP-19282 Aux Id: PR-8907

      • The line_coverage option would be ignored if given in a compile() attribute within a module.

        Own Id: OTP-19309 Aux Id: GH-8942, PR-8970

      • A segment matching a float in a binary generator will now skip any invalid float (such as a NaN) and continue matching the rest of the binary. Before this correction, the comprehension would stop as soon as an invalid float was encountered.

        Example:

        1> BadFloat = <<-1:64>>.
        +<<"ÿÿÿÿÿÿÿÿ">>
        +2> [X || <<X:64/float>> <= <<0.0/float,BadFloat/binary,42.0/float>>].
        +[0.0,42.0]

        Own Id: OTP-19331 Aux Id: PR-8978

      Compiler 8.5.3

      Fixed Bugs and Malfunctions

      • In rare circumstances, the destructive tuple update optimization could be applied when it was unsafe.

        Own Id: OTP-19340 Aux Id: GH-9014, PR-9024

      • In rare circumstances involving appending to multiple binaries, the compile could emit unsafe code that would crash the runtime system.

        Own Id: OTP-19374 Aux Id: GH-9100, PR-9111

      Compiler 8.5.2

      Fixed Bugs and Malfunctions

      • Fixed a crash in an optimization pass relating to appending binaries.

        Own Id: OTP-19168 Aux Id: GH-8630

      • Fixed a bug in the compiler's alias analysis pass that could make it emit unsafe code.

        Own Id: OTP-19178 Aux Id: PR-8686

      Compiler 8.5.1

      Fixed Bugs and Malfunctions

      • One of the compiler's optimization passes would get very slow when compiling certain modules. The compiler will now automatically disable that pass for input that would trigger the slowdown.

        Own Id: OTP-19131 Aux Id: PR-8567

      • Fix +deterministic to work properly with documentation attributes.

        Own Id: OTP-19142 Aux Id: PR-8585, GH-8579

      Compiler 8.5

      Fixed Bugs and Malfunctions

      • Generators for binary comprehensions could be evaluated before it was known that they would be needed. That could result in a binary comprehensions failing if a generator that should not be evaluated until later failed.

        As an example, consider this module:

        -module(t).
        +-export([f/0]).
         
        -f() ->
        -    <<0 || _ <- [], _ <- ok, false>>.

        In Erlang/OTP 26 it would fail like so:

        1> t:f().
        +f() ->
        +    <<0 || _ <- [], _ <- ok, false>>.

        In Erlang/OTP 26 it would fail like so:

        1> t:f().
         ** exception error: bad generator ok
        -     in function  t:f/0 (t.erl, line 6)

        In Erlang/OTP 27 it returns an empty binary:

        1> t:f().
        -<<>>

        Own Id: OTP-18703 Aux Id: GH-7494, PR-7538

      • The documentation for the preprocessor now mentions that defined(Name) can be called in the condition for an -if or -elif directive to test whether Name is the name of a defined macro. (This feature was implemented in OTP 21.)

        If a function call in an -if or -elif with a name that is not the name of a guard BIF, there would not be a compilation error, but would instead cause the lines following the directive to be skipped. This has now been changed to be a compilation error.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-18784 Aux Id: GH-7706, PR-7726

      Improvements and New Features

      • The compiler now emits nicer error message for function head mismatches. -For example, given:

        a() -> ok;
        -a(_) -> error.

        Erlang/OTP 26 and earlier would emit a diagnostic similar to:

        t.erl:6:1: head mismatch
        +     in function  t:f/0 (t.erl, line 6)

        In Erlang/OTP 27 it returns an empty binary:

        1> t:f().
        +<<>>

        Own Id: OTP-18703 Aux Id: GH-7494, PR-7538

      • The documentation for the preprocessor now mentions that defined(Name) can be called in the condition for an -if or -elif directive to test whether Name is the name of a defined macro. (This feature was implemented in OTP 21.)

        If a function call in an -if or -elif with a name that is not the name of a guard BIF, there would not be a compilation error, but would instead cause the lines following the directive to be skipped. This has now been changed to be a compilation error.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-18784 Aux Id: GH-7706, PR-7726

      Improvements and New Features

      • The compiler now emits nicer error message for function head mismatches. +For example, given:

        a() -> ok;
        +a(_) -> error.

        Erlang/OTP 26 and earlier would emit a diagnostic similar to:

        t.erl:6:1: head mismatch
         %    6| a(_) -> error.
         %     | ^

        while in Erlang/OTP 27 the diagnostic is similar to:

        t.erl:6:1: head mismatch: function a with arities 0 and 1 is regarded as two distinct functions. Is the number of arguments incorrect or is the semicolon in a/0 unwanted?
         %    6| a(_) -> error.
        -%     | ^

        Own Id: OTP-18648 Aux Id: PR-7383

      • The compiler now optimizes creation of binaries that are known to be constant.

        Consider this example:

        bin() ->
        -    C = char(),
        -    <<C>>.
        -
        -char() -> $*.

        Essentially, the compiler rewrites the example to the slightly more efficient:

        bin() ->
        -    _ = char(),
        -    <<$*>>.
        -
        -char() -> $*.

        Own Id: OTP-18673 Aux Id: PR-7474, ERIERL-964

      • The compiler will now merge consecutive updates of the same record.

        As an example, the body of the following function will be combined into a single tuple creation instruction:

        -record(r, {a,b,c,d}).
        -
        -update(Value) ->
        -    R0 = #href_anchor"ss">r{},
        -    R1 = R0#r{a=Value},
        -    R2 = R1#r{b=2},
        -    R2#r{c=3}.

        Own Id: OTP-18680 Aux Id: PR-7491, PR-8086, ERIERL-967

      • Improved the performance of the alias analysis pass.

        Own Id: OTP-18714 Aux Id: PR-7528, GH-7432

      • -spec attributes are now used for documentation.

        Own Id: OTP-18801 Aux Id: PR-7739

      • Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code.

        There are also new APIs to support native coverage without using the cover tool.

        To instrument code for native coverage it must be compiled with the line_coverage option.

        To enable native coverage in the runtime system, start it like so:

        $ erl +JPcover true

        There are also the following new functions for supporting native coverage:

        Own Id: OTP-18856 Aux Id: PR-7856

      • EEP-59 - Documentation Attributes has been implemented.

        Documentation attributes can be used to document functions, types, callbacks, and modules. +% | ^

      Own Id: OTP-18648 Aux Id: PR-7383

    • The compiler now optimizes creation of binaries that are known to be constant.

      Consider this example:

      bin() ->
      +    C = char(),
      +    <<C>>.
      +
      +char() -> $*.

      Essentially, the compiler rewrites the example to the slightly more efficient:

      bin() ->
      +    _ = char(),
      +    <<$*>>.
      +
      +char() -> $*.

      Own Id: OTP-18673 Aux Id: PR-7474, ERIERL-964

    • The compiler will now merge consecutive updates of the same record.

      As an example, the body of the following function will be combined into a single tuple creation instruction:

      -record(r, {a,b,c,d}).
      +
      +update(Value) ->
      +    R0 = #href_anchor"ss">r{},
      +    R1 = R0#r{a=Value},
      +    R2 = R1#r{b=2},
      +    R2#r{c=3}.

      Own Id: OTP-18680 Aux Id: PR-7491, PR-8086, ERIERL-967

    • Improved the performance of the alias analysis pass.

      Own Id: OTP-18714 Aux Id: PR-7528, GH-7432

    • -spec attributes are now used for documentation.

      Own Id: OTP-18801 Aux Id: PR-7739

    • Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code.

      There are also new APIs to support native coverage without using the cover tool.

      To instrument code for native coverage it must be compiled with the line_coverage option.

      To enable native coverage in the runtime system, start it like so:

      $ erl +JPcover true

      There are also the following new functions for supporting native coverage:

      Own Id: OTP-18856 Aux Id: PR-7856

    • EEP-59 - Documentation Attributes has been implemented.

      Documentation attributes can be used to document functions, types, callbacks, and modules. The keyword -moduledoc "Documentation here". is used to document modules, while -doc "Documentation here". can be used on top of functions, types, and callbacks to document them, respectively.

      • Types, callbacks, and function documentation can be set to hidden either via -doc false or -doc hidden. When documentation attributes mark a type as hidden, they will not be part of the documentation.

      • The documentation from moduledoc and doc gets added by default to the binary beam file, following the format of EEP-48.

      • Using the compiler flag warn_missing_doc will raise a warning when -doc attributes are missing in exported functions, types, and callbacks.

      • Using the compiler flag warn_missing_spec_documented will raise a warning when -spec attributes are missing in documented functions, types, and callbacks.

      • moduledocs and docs may refer to external files to be embedded, such as -doc {file, "README.md"}., which refers to the file README.md found in the current working directory.

      • The compiler warns about exported functions whose specs refer to hidden types. Thus, there will be warnings when a hidden type (meaning, the type is not part of the documentation) gets used in an exported function.

      Own Id: OTP-18916 Aux Id: PR-7936

    • The documentation has been migrated to use Markdown and ExDoc.

      Own Id: OTP-18955 Aux Id: PR-8026

    • The order in which the compiler looks up options has changed.

      When there is a conflict in the compiler options given in the -compile() attribute and options given to the compiler, the options given in the -compile() attribute overrides the option given to the compiler, which in turn overrides options given in the ERL_COMPILER_OPTIONS environment variable.

      Example:

      If some_module.erl has the following attribute:

      -compile([nowarn_missing_spec]).

      and the compiler is invoked like so:

      % erlc +warn_missing_spec some_module.erl

      no warnings will be issued for functions that do not have any specs.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-18968 Aux Id: GH-6979, PR-8093

    • Safe destructive update of tuples has been implemented in the compiler and runtime system. This allows the VM to update tuples in-place when it is safe to do so, thus improving performance by doing less copying but also by producing less garbage.

      Example:

      -record(rec, {a,b,c}).
      +spec attributes are missing in documented functions, types, and callbacks.

    • moduledocs and docs may refer to external files to be embedded, such as -doc {file, "README.md"}., which refers to the file README.md found in the current working directory.

    • The compiler warns about exported functions whose specs refer to hidden types. Thus, there will be warnings when a hidden type (meaning, the type is not part of the documentation) gets used in an exported function.

    Own Id: OTP-18916 Aux Id: PR-7936

  • The documentation has been migrated to use Markdown and ExDoc.

    Own Id: OTP-18955 Aux Id: PR-8026

  • The order in which the compiler looks up options has changed.

    When there is a conflict in the compiler options given in the -compile() attribute and options given to the compiler, the options given in the -compile() attribute overrides the option given to the compiler, which in turn overrides options given in the ERL_COMPILER_OPTIONS environment variable.

    Example:

    If some_module.erl has the following attribute:

    -compile([nowarn_missing_spec]).

    and the compiler is invoked like so:

    % erlc +warn_missing_spec some_module.erl

    no warnings will be issued for functions that do not have any specs.

    POTENTIAL INCOMPATIBILITY

    Own Id: OTP-18968 Aux Id: GH-6979, PR-8093

  • Safe destructive update of tuples has been implemented in the compiler and runtime system. This allows the VM to update tuples in-place when it is safe to do so, thus improving performance by doing less copying but also by producing less garbage.

    Example:

    -record(rec, {a,b,c}).
     
    -update(#href_anchor"ss">rec{a=needs_update,b=N}=R0) ->
    -    R = R0#rec{a=up_to_date},
    +update(#href_anchor"ss">rec{a=needs_update,b=N}=R0) ->
    +    R = R0#rec{a=up_to_date},
         if
             N < 0 ->
    -            R#rec{c=negative};
    +            R#rec{c=negative};
             N == 0 ->
    -            R#rec{c=zero};
    +            R#rec{c=zero};
             N > 0 ->
    -            R#rec{c=positive}
    +            R#rec{c=positive}
         end.

    The record updates in each of the three clauses of the if can safely be done in-place, because variable R is not used again.

    Own Id: OTP-18972 Aux Id: PR-8090

  • Improved the match context reuse optimization slightly, allowing match contexts to be passed as-is to bit_size/1 and byte_size/1.

    Own Id: OTP-18987

  • erl_lint (and by extension the compiler) will now warn for code using deprecated callbacks.

    The only callback currenly deprecated is format_status/2 in gen_server, gen_event and gen_statem.

    You can use nowarn_deprecated_callback to silence the warning.

    Own Id: OTP-19010 Aux Id: PR-8205

  • Compiler 8.4.3.4

    Fixed Bugs and Malfunctions

    • Fixed broken type inference for lists:mapfoldl/r.

      Own Id: OTP-19845 Aux Id: GH-10354, PR-10358

    Compiler 8.4.3.3

    Fixed Bugs and Malfunctions

    • Fix a bug where unloaded nifs can crash the compiler.

      Own Id: OTP-19600 Aux Id: PR-9737, GH-9715

    Compiler 8.4.3.2

    Fixed Bugs and Malfunctions

    • Fixed a bug where bogus code was generated for consecutive calls to erlang:setelement/2, potentially crashing the emulator.

      Own Id: OTP-19270 Aux Id: GH-8783 PR-8898

    Compiler 8.4.3.1

    Fixed Bugs and Malfunctions

    • Fixed a crash in an optimization pass relating to appending binaries.

      Own Id: OTP-19168 Aux Id: GH-8630

    • Fixed a bug in the compiler's alias analysis pass that could make it emit unsafe code.

      Own Id: OTP-19178 Aux Id: PR-8686

    Compiler 8.4.3

    Fixed Bugs and Malfunctions

    • In rare circumstances, the compiler code generate unsafe code for a bit syntax match.

      Own Id: OTP-19019

    • In rare circumstances, binary matches that were supposed to succeed failed.

      Own Id: OTP-19035 Aux Id: GH-8280, PR-8284

    • Fixed a bug where a fun's environment could be overridden by an argument if all of the following conditions were met:

      • The fun was declared in the module that called it.
      • The fun's target was statically known.
      • The fun was called with a number of extra arguments equal to the number of environment variables.

      Own Id: OTP-19045 Aux Id: GH-8316

    Compiler 8.4.2

    Fixed Bugs and Malfunctions

    • In rare circumstances, an unsafe optimization could cause the compiler to generate incorrect code for list matching.

      Own Id: OTP-19003 Aux Id: GH-8187, PR-8189

    Improvements and New Features

    • Fix the compilation server to restart if the applications in its lib dir changes inbetween erlc invokations.

      Own Id: OTP-18936

    Compiler 8.4.1

    Fixed Bugs and Malfunctions

    • The compiler could become extremely slow for modules containing huge functions.

      Own Id: OTP-18770 Aux Id: GH-7667, PR-7672

    Compiler 8.4

    Fixed Bugs and Malfunctions

    • The compiler could run forever when compiling a call to is_record/3 with a huge positive tuple size. The call /usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/ssa_checks.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1093)) --- old//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/ssa_checks.html 2026-08-21 04:00:19.838297463 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/compiler-9.0.6.1/doc/html/ssa_checks.html 2026-08-21 04:00:19.838297463 +0000 @@ -100,32 +100,32 @@ functionality.

      Syntax

      SSA checks are embedded in the source code as comments starting with with one of %ssa%, %%ssa% or %%%ssa%. This is a short introduction the syntax, for the full syntax please refer to the -ssa_check_when_clause production in erl_parse.yrl.

      SSA checks can be placed inside any Erlang function, for example:

      t0() ->
      +ssa_check_when_clause production in erl_parse.yrl.

      SSA checks can be placed inside any Erlang function, for example:

      t0() ->
       %ssa% () when post_ssa_opt ->
       %ssa%   ret(#{}).
      -  #{}.

      will check that t0/0 returns the literal #{}. If we want to check -that a function returns its first formal parameter, we can write:

      t1(A, _B) ->
      +  #{}.

      will check that t0/0 returns the literal #{}. If we want to check +that a function returns its first formal parameter, we can write:

      t1(A, _B) ->
       %ssa% (X, _) when post_ssa_opt ->
       %ssa%   ret(X).
         A.

      Note how we match the first formal parameter using X. The reason for having our own formal parameters for the SSA check, is that we don't want to introduce new identifiers at the Erlang level to support SSA-level checks. Consider if t1/2 had been defined as t1([A|As], B) we would have had to introduce a new identifier for the aggregate -value [A|As].

      The full syntax for a SSA check clause is:

      <expected-result>? (<formals>) when <pipeline-location> -> <checks> '.'

      where <expected-result> can be one of pass (the check must +value [A|As].

      The full syntax for a SSA check clause is:

      <expected-result>? (<formals>) when <pipeline-location> -> <checks> '.'

      where <expected-result> can be one of pass (the check must succeed), fail and xfail (the check must fail). Omitting <expected-result> is parsed as an implicit pass.

      <formals> is a comma-separated list of variables.

      <pipeline-location> specifies when in the compiler pipeline to run the checks. For now the only supported value for <pipeline-location> is post_ssa_opt which runs the checks after the ssa_opt pass.

      <checks> is a comma-separated list of matches against the BEAM SSA -code. For non-flow-control operations the syntax is:

      <variable> = <operation> ( <arguments> ) <annotation>?

      where <operation> is the #b_set.op field from the internal SSA -representation. BIFs are written as bif:<atom>.

      <arguments> is a comma-separated list of variables or literals.

      For flow control operations and labels, the syntax is as follows:

      br(<bool>, <true-label>, <false-label>)
      +code. For non-flow-control operations the syntax is:

      <variable> = <operation> ( <arguments> ) <annotation>?

      where <operation> is the #b_set.op field from the internal SSA +representation. BIFs are written as bif:<atom>.

      <arguments> is a comma-separated list of variables or literals.

      For flow control operations and labels, the syntax is as follows:

      br(<bool>, <true-label>, <false-label>)
       
      -switch(<value>, <fail-label>, [{<label>,<value>},...])
      +switch(<value>, <fail-label>, [{<label>,<value>},...])
       
      -ret(<value>)
      +ret(<value>)
       
       label <value>

      where <value> is a literal or a variable.

      A check can also include an assertion on operation annotations. The assertion is written as a map-like pattern following the argument -list, for example:

      t0() ->
      +list, for example:

      t0() ->
       %ssa% () when post_ssa_opt ->
       %ssa% _ = call(fun return_int/0) { result_type => {t_integer,{17,17}},
       %ssa%                              location => {_,32} },
      @@ -133,9 +133,9 @@
       %ssa%    result_type => {t_tuple,2,true,#{1 => {t_integer,{1,1}},
       %ssa%                                     2 => {t_integer,{2,2}}}}
       %ssa% }.
      -    X = return_int(),
      -    Y = return_tuple(),
      -    {X, Y}.

      Semantics

      When an SSA assertion is matched against the BEAM SSA for a function, + X = return_int(), + Y = return_tuple(), + {X, Y}.

      Semantics

      When an SSA assertion is matched against the BEAM SSA for a function, patterns are applied sequentially. If the current pattern doesn't match, the checker tries with the next instruction. If the checker reaches the end of the SSA representation without having matched all /usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> crypto - 5.8.3.2 - urn:uuid:7ff0da9f-9e2d-d8c7-87fe-ece5e56945f1 + urn:uuid:18cfdb76-7705-1a31-7d9c-b171c89f2748 en - 2026-08-21T03:49:28Z + 2042-09-22T17:08:27Z /usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/crypto.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1823)) --- old//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/crypto.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/crypto.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -3686,7 +3686,7 @@ -

      rsa_public() = [E, N]
      rsa_private() = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]

      Where E is the public exponent, N is public modulus and D is the private +

      rsa_public() = [E, N]
      rsa_private() = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]

      Where E is the public exponent, N is public modulus and D is the private exponent. The longer key format contains redundant information that will make the calculation faster. P1 and P2 are first and second prime factors. E1 and E2 are first and second exponents. C is the CRT coefficient. The terminology is @@ -6510,9 +6510,9 @@

      Create a generator for rand and save it in the process dictionary.

      Equivalent to rand_seed_s/0 but also saves the returned state object (generator) in the process dictionary. That is, -it is equivalent to rand:seed(rand_seed_s()).

      See rand:seed/1 and rand_seed_s/0.

      Example

      _ = crypto:rand_seed(),
      -IntegerValue = rand:uniform(42), % 1 .. 42
      -FloatValue = rand:uniform().     % [0.0; 1.0)

      Note

      Note that when using the process dictionary for cryptographically +it is equivalent to rand:seed(rand_seed_s()).

      See rand:seed/1 and rand_seed_s/0.

      Example

      _ = crypto:rand_seed(),
      +IntegerValue = rand:uniform(42), % 1 .. 42
      +FloatValue = rand:uniform().     % [0.0; 1.0)

      Note

      Note that when using the process dictionary for cryptographically secure random numbers one has to ensure that no code called between initializing the generator and between generating numbers accidentally alters the generator state in the process dictionary.

      The safe approach is to use the rand functions that @@ -6552,9 +6552,9 @@ and save it in the process dictionary.

      Equivalent rand_seed_alg_s/1 but also saves the returned state object (generator) in the process dictionary. That is, it is equivalent to rand:seed(rand_seed_alg_s(Alg)).

      See rand:seed/1 and rand_seed_alg_s/1. -Note the warning about the usage of the process dictionary in rand_seed/0.

      Example

      _ = crypto:rand_seed_alg(crypto_cache),
      -IntegerValue = rand:uniform(42), % 1 .. 42
      -FloatValue = rand:uniform().     % [0.0; 1.0)
      +Note the warning about the usage of the process dictionary in rand_seed/0.

      Example

      _ = crypto:rand_seed_alg(crypto_cache),
      +IntegerValue = rand:uniform(42), % 1 .. 42
      +FloatValue = rand:uniform().     % [0.0; 1.0)
      @@ -6589,12 +6589,12 @@ and save it in the process dictionary.

      Equivalent to rand_seed_alg_s/2 but also saves the returned state object (generator) in the process dictionary. That is, it is equivalent to rand:seed(rand_seed_alg_s(Alg, Seed)).

      See rand:seed/1 and rand_seed_alg_s/2. -Note the warning about the usage of the process dictionary in rand_seed/0.

      Example

      _ = crypto:rand_seed_alg(crypto_aes, "my seed"),
      -IntegerValue = rand:uniform(42), % 1 .. 42
      -FloatValue = rand:uniform(),     % [0.0; 1.0)
      -_ = crypto:rand_seed_alg(crypto_aes, "my seed"),
      -IntegerValue = rand:uniform(42), % Same values
      -FloatValue = rand:uniform().     % again
      +Note the warning about the usage of the process dictionary in rand_seed/0.

      Example

      _ = crypto:rand_seed_alg(crypto_aes, "my seed"),
      +IntegerValue = rand:uniform(42), % 1 .. 42
      +FloatValue = rand:uniform(),     % [0.0; 1.0)
      +_ = crypto:rand_seed_alg(crypto_aes, "my seed"),
      +IntegerValue = rand:uniform(42), % Same values
      +FloatValue = rand:uniform().     % again
      @@ -6628,9 +6628,9 @@ which when used by the rand functions produce cryptographically strong random number.

      See also rand:seed_s/1 and for example rand:uniform_s/2.

      If Alg is crypto this function is equivalent to rand_seed_s/0.

      If Alg is crypto_cache the returned generator fetches random data with OpenSSL's RAND_bytes and caches it as 56 bit numbers -which makes calculations fast on 64 bit machines.

      Example

      S0 = crypto:rand_seed_alg_s(crypto_cache),
      -{IntegerValue, S1} = rand:uniform(42, S0), % 1 .. 42
      -{FloatValue, S2} = rand:uniform(S1).       % [0.0; 1.0)

      May cause the rand functions using this state object +which makes calculations fast on 64 bit machines.

      Example

      S0 = crypto:rand_seed_alg_s(crypto_cache),
      +{IntegerValue, S1} = rand:uniform(42, S0), % 1 .. 42
      +{FloatValue, S2} = rand:uniform(S1).       % [0.0; 1.0)

      May cause the rand functions using this state object to raise the exception error:low_entropy in case the random generator failed due to lack of secure "randomness".

      The cache size can be changed from its default value using the crypto app's configuration parameter rand_cache_size.

      Note

      The state returned from this function cannot be used to get a reproducible @@ -6679,12 +6679,12 @@ for the same seed.

      • If you need cryptographically strong random numbers use rand_seed_alg_s/1 with Alg =:= crypto or Alg =:= crypto_cache.
      • If you need to be able to repeat the sequence use this function with Alg =:= crypto_aes.
      • If you do not need the statistical quality of this function, there are faster -algorithms in the rand module.

      Example

      S0 = crypto:rand_seed_alg_s(crypto_aes, "my seed"),
      -{IntegerValue, S1} = rand:uniform(42, S0), % 1 .. 42
      -{FloatValue, S2 = rand:uniform(S1),        % [0.0; 1.0)
      -S3 = crypto:rand_seed_alg_s(crypto_aes, "my seed"),
      -{IntegerValue, S4} = rand:uniform(42, S3), % Same values
      -{FloatValue, S5} = rand:uniform(S4).       % again

      Thanks to the used generator the state object supports the +algorithms in the rand module.

    Example

    S0 = crypto:rand_seed_alg_s(crypto_aes, "my seed"),
    +{IntegerValue, S1} = rand:uniform(42, S0), % 1 .. 42
    +{FloatValue, S2 = rand:uniform(S1),        % [0.0; 1.0)
    +S3 = crypto:rand_seed_alg_s(crypto_aes, "my seed"),
    +{IntegerValue, S4} = rand:uniform(42, S3), % Same values
    +{FloatValue, S5} = rand:uniform(S4).       % again

    Thanks to the used generator the state object supports the rand:jump/0,1 function with distance 2^512.

    Numbers are generated in batches and cached for speed reasons. The cache size can be changed from its default value using the crypto app's configuration parameter rand_cache_size.

    @@ -6721,8 +6721,8 @@ which when used by the rand functions produce cryptographically strong random numbers (based on OpenSSL's BN_rand_range function). See also rand:seed_s/1, and for example -rand:uniform_s/2.

    Example

    S0 = crypto:rand_seed_s(),
    -{RandomInteger, S1} = rand:uniform_s(1000, S0).

    May cause the rand functions using this state object +rand:uniform_s/2.

    Example

    S0 = crypto:rand_seed_s(),
    +{RandomInteger, S1} = rand:uniform_s(1000, S0).

    May cause the rand functions using this state object to raise the exception error:low_entropy in case the random generator failed due to lack of secure "randomness".

    Note

    The state returned from this function cannot be used to get a reproducible random sequence as from the other rand functions, since that would @@ -7335,14 +7335,14 @@ -

    Get information about crypto and the OpenSSL backend.

    Returns a map with information about the compilation and linking of crypto.

    Example:

    1> crypto:info().
    -#{compile_type => normal,
    +

    Get information about crypto and the OpenSSL backend.

    Returns a map with information about the compilation and linking of crypto.

    Example:

    1> crypto:info().
    +#{compile_type => normal,
       cryptolib_version_compiled => "OpenSSL 3.0.0 7 sep 2021",
       cryptolib_version_linked => "OpenSSL 3.0.0 7 sep 2021",
       link_type => dynamic,
       otp_crypto_version => "5.0.2",
       fips_provider_available => true,
    -  fips_provider_buildinfo => "3.0.0"}
    +  fips_provider_buildinfo => "3.0.0"}
     2>

    More association types than documented may be present in the map. Some of the associations (like fips) may be absent if not supported.

    @@ -7411,8 +7411,8 @@

    Get the name and version of the libraries used by crypto.

    Name is the name of the library. VerNum is the numeric version according to the library's own versioning scheme. VerStr contains a text variant of the -version.

    > info_lib().
    -[{<<"OpenSSL">>,269484095,<<"OpenSSL 1.1.0c  10 Nov 2016"">>}]

    Note

    From OTP R16 the numeric version represents the version of the OpenSSL +version.

    > info_lib().
    +[{<<"OpenSSL">>,269484095,<<"OpenSSL 1.1.0c  10 Nov 2016"">>}]

    Note

    From OTP R16 the numeric version represents the version of the OpenSSL header files (openssl/opensslv.h) used when crypto was compiled. The text variant represents the libcrypto library used at runtime. In earlier OTP versions both numeric and text was taken from the library.

    /usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/engine_keys.xhtml differs (HTML document, ASCII text, with very long lines (990)) --- old//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/engine_keys.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/engine_keys.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -35,30 +35,30 @@ string or binary and depends on the Engine loaded
  • an Erlang map is constructed with the Engine reference, the key reference and possibly a key passphrase if needed by the Engine. See the Reference Manual for details of the map.
  • Use Cases

    Sign with an engine stored private key

    This example shows how to construct a key reference that is used in a sign -operation. The actual key is stored in the engine that is loaded at prompt 1.

    1> {ok, EngineRef} = crypto:engine_load(....).
    +operation. The actual key is stored in the engine that is loaded at prompt 1.

    1> {ok, EngineRef} = crypto:engine_load(....).
     ...
    -{ok,#Ref<0.2399045421.3028942852.173962>}
    -2> PrivKey = #{engine => EngineRef,
    -               key_id => "id of the private key in Engine"}.
    +{ok,#Ref<0.2399045421.3028942852.173962>}
    +2> PrivKey = #{engine => EngineRef,
    +               key_id => "id of the private key in Engine"}.
     ...
    -3> Signature = crypto:sign(rsa, sha, <<"The message">>, PrivKey).
    -<<65,6,125,254,54,233,84,77,83,63,168,28,169,214,121,76,
    -  207,177,124,183,156,185,160,243,36,79,125,230,231,...>>

    Verify with an engine stored public key

    Here the signature and message in the last example is verifyed using the public +3> Signature = crypto:sign(rsa, sha, <<"The message">>, PrivKey). +<<65,6,125,254,54,233,84,77,83,63,168,28,169,214,121,76, + 207,177,124,183,156,185,160,243,36,79,125,230,231,...>>

    Verify with an engine stored public key

    Here the signature and message in the last example is verifyed using the public key. The public key is stored in an engine, only to exemplify that it is -possible. The public key could of course be handled openly as usual.

    4> PublicKey = #{engine => EngineRef,
    -                 key_id => "id of the public key in Engine"}.
    +possible. The public key could of course be handled openly as usual.

    4> PublicKey = #{engine => EngineRef,
    +                 key_id => "id of the public key in Engine"}.
     ...
    -5> crypto:verify(rsa, sha, <<"The message">>, Signature, PublicKey).
    +5> crypto:verify(rsa, sha, <<"The message">>, Signature, PublicKey).
     true
     6>

    Using a password protected private key

    The same example as the first sign example, except that a password protects the -key down in the Engine.

    6> PrivKeyPwd = #{engine => EngineRef,
    +key down in the Engine.

    6> PrivKeyPwd = #{engine => EngineRef,
                       key_id => "id of the pwd protected private key in Engine",
    -		  password => "password"}.
    +		  password => "password"}.
     ...
    -7> crypto:sign(rsa, sha, <<"The message">>, PrivKeyPwd).
    -<<140,80,168,101,234,211,146,183,231,190,160,82,85,163,
    +7> crypto:sign(rsa, sha, <<"The message">>, PrivKeyPwd).
    +<<140,80,168,101,234,211,146,183,231,190,160,82,85,163,
       175,106,77,241,141,120,72,149,181,181,194,154,175,76,
    -  223,...>>
    +  223,...>>
     8>
    /usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/engine_load.xhtml differs (HTML document, ASCII text, with very long lines (1099)) --- old//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/engine_load.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/engine_load.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -26,32 +26,32 @@ performance over its software-based counterpart, which is known as cryptographic acceleration.

    Note

    The file name requirement on the engine dynamic library can differ between SSL versions.

    Use Cases

    Dynamically load an engine from default directory

    If the engine is located in the OpenSSL/LibreSSL installation engines -directory.

    1> {ok, Engine} = crypto:engine_load(<<"otp_test_engine">>, [], []).
    - {ok, #Ref}

    Load an engine with the dynamic engine

    Load an engine with the help of the dynamic engine by giving the path to the -library.

     2> {ok, Engine} = crypto:engine_load(<<"dynamic">>,
    -                                      [{<<"SO_PATH">>,
    -                                        <<"/some/path/otp_test_engine.so">>},
    -                                       {<<"ID">>, <<"MD5">>},
    -                                       <<"LOAD">>],
    -                                      []).
    - {ok, #Ref}

    Load an engine and replace some methods

    Load an engine with the help of the dynamic engine and just replace some engine -methods.

     3> {ok, Engine} = crypto:engine_load(<<"dynamic">>,
    -                                      [{<<"SO_PATH">>,
    -                                        <<"/some/path/otp_test_engine.so">>},
    -                                       {<<"ID">>, <<"MD5">>},
    -                                       <<"LOAD">>],
    -                                      []).
    -{ok, #Ref}
    -4> ok = crypto:engine_register(Engine, [engine_method_digests]).
    +directory.

    1> {ok, Engine} = crypto:engine_load(<<"otp_test_engine">>, [], []).
    + {ok, #Ref}

    Load an engine with the dynamic engine

    Load an engine with the help of the dynamic engine by giving the path to the +library.

     2> {ok, Engine} = crypto:engine_load(<<"dynamic">>,
    +                                      [{<<"SO_PATH">>,
    +                                        <<"/some/path/otp_test_engine.so">>},
    +                                       {<<"ID">>, <<"MD5">>},
    +                                       <<"LOAD">>],
    +                                      []).
    + {ok, #Ref}

    Load an engine and replace some methods

    Load an engine with the help of the dynamic engine and just replace some engine +methods.

     3> {ok, Engine} = crypto:engine_load(<<"dynamic">>,
    +                                      [{<<"SO_PATH">>,
    +                                        <<"/some/path/otp_test_engine.so">>},
    +                                       {<<"ID">>, <<"MD5">>},
    +                                       <<"LOAD">>],
    +                                      []).
    +{ok, #Ref}
    +4> ok = crypto:engine_register(Engine, [engine_method_digests]).
     ok

    Load with the ensure loaded function

    This function makes sure the engine is loaded just once and the ID is added to the internal engine list of OpenSSL. The following calls to the function will -check if the ID is loaded and then just get a new reference to the engine.

     5> {ok, Engine} = crypto:ensure_engine_loaded(<<"MD5">>,
    -                                               <<"/some/path/otp_test_engine.so">>).
    - {ok, #Ref}

    To remove the tag from the OpenSSL engine list use crypto:engine_remove/1.

     6> crypto:engine_remove(Engine).
    +check if the ID is loaded and then just get a new reference to the engine.

     5> {ok, Engine} = crypto:ensure_engine_loaded(<<"MD5">>,
    +                                               <<"/some/path/otp_test_engine.so">>).
    + {ok, #Ref}

    To remove the tag from the OpenSSL engine list use crypto:engine_remove/1.

     6> crypto:engine_remove(Engine).
      ok

    To unload it use crypto:engine_unload/1 which removes the references to the -engine.

     6> crypto:engine_unload(Engine).
    - ok

    List all engines currently loaded

     8> crypto:engine_list().
    -[<<"dynamic">>, <<"MD5">>]
    +engine.

     6> crypto:engine_unload(Engine).
    + ok

    List all engines currently loaded

     8> crypto:engine_list().
    +[<<"dynamic">>, <<"MD5">>]
    /usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/new_api.xhtml differs (HTML document, ASCII text, with very long lines (2413)) --- old//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/new_api.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.epub/OEBPS/new_api.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -42,85 +42,85 @@ initialises the crypto context. One or more calls crypto_update/2 does the actual encryption or decryption for each block.

    This example shows first the encryption of two blocks and then decryptions of the cipher text, but divided into three blocks just to show that it is possible -to divide the plain text and cipher text differently for some ciphers:

    	1> application:start(crypto).
    +to divide the plain text and cipher text differently for some ciphers:

    	1> application:start(crypto).
     	ok
    -	2> Key = <<1:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    -	3> IV = <<0:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
    -	4> StateEnc = crypto:crypto_init(aes_128_ctr, Key, IV, true). % encrypt -> true
    +	2> Key = <<1:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    +	3> IV = <<0:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
    +	4> StateEnc = crypto:crypto_init(aes_128_ctr, Key, IV, true). % encrypt -> true
     	#Ref<0.3768901617.1128660993.124047>
    -	5> crypto:crypto_update(StateEnc, <<"First bytes">>).
    -	<<67,44,216,166,25,130,203,5,66,6,162>>
    -	6> crypto:crypto_update(StateEnc, <<"Second bytes">>).
    -	<<16,79,94,115,234,197,94,253,16,144,151,41>>
    +	5> crypto:crypto_update(StateEnc, <<"First bytes">>).
    +	<<67,44,216,166,25,130,203,5,66,6,162>>
    +	6> crypto:crypto_update(StateEnc, <<"Second bytes">>).
    +	<<16,79,94,115,234,197,94,253,16,144,151,41>>
     	7>
    -	7> StateDec = crypto:crypto_init(aes_128_ctr, Key, IV, false). % decrypt -> false
    +	7> StateDec = crypto:crypto_init(aes_128_ctr, Key, IV, false). % decrypt -> false
     	#Ref<0.3768901617.1128660994.124255>
    -	8> crypto:crypto_update(StateDec, <<67,44,216,166,25,130,203>>).
    -	<<"First b">>
    -	9> crypto:crypto_update(StateDec, <<5,66,6,162,16,79,94,115,234,197,
    -        94,253,16,144,151>>).
    -	<<"ytesSecond byte">>
    -	10> crypto:crypto_update(StateDec, <<41>>).
    -	<<"s">>
    +	8> crypto:crypto_update(StateDec, <<67,44,216,166,25,130,203>>).
    +	<<"First b">>
    +	9> crypto:crypto_update(StateDec, <<5,66,6,162,16,79,94,115,234,197,
    +        94,253,16,144,151>>).
    +	<<"ytesSecond byte">>
    +	10> crypto:crypto_update(StateDec, <<41>>).
    +	<<"s">>
     	11>

    Note that the internal data that the StateEnc and StateDec references are destructivly updated by the calls to crypto_update/2. This is to gain time in the calls of the nifs interfacing the cryptolib. In a loop where the state is saved in the loop's state, it also saves one update of the loop state per crypto operation.

    For example, a simple server receiving text parts to encrypt and send the result -back to the one who sent them (the Requester):

    	encode(Crypto, Key, IV) ->
    -	crypto_loop(crypto:crypto_init(Crypto, Key, IV, true)).
    +back to the one who sent them (the Requester):

    	encode(Crypto, Key, IV) ->
    +	crypto_loop(crypto:crypto_init(Crypto, Key, IV, true)).
     
    -	crypto_loop(State) ->
    +	crypto_loop(State) ->
     	receive
    -        {Text, Requester} ->
    -        Requester ! crypto:crypto_update(State, Text),
    -	loop(State)
    +        {Text, Requester} ->
    +        Requester ! crypto:crypto_update(State, Text),
    +	loop(State)
     	end.

    Example of crypto_one_time/5

    The same example as in the previous section, -but now with one call to crypto_one_time/5:

    	1> Key = <<1:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    -	2> IV = <<0:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
    -	3> Txt = [<<"First bytes">>,<<"Second bytes">>].
    -	[<<"First bytes">>,<<"Second bytes">>]
    -	4> crypto:crypto_one_time(aes_128_ctr, Key, IV, Txt, true).
    -	<<67,44,216,166,25,130,203,5,66,6,162,16,79,94,115,234,
    -	197,94,253,16,144,151,41>>
    +but now with one call to crypto_one_time/5:

    	1> Key = <<1:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    +	2> IV = <<0:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
    +	3> Txt = [<<"First bytes">>,<<"Second bytes">>].
    +	[<<"First bytes">>,<<"Second bytes">>]
    +	4> crypto:crypto_one_time(aes_128_ctr, Key, IV, Txt, true).
    +	<<67,44,216,166,25,130,203,5,66,6,162,16,79,94,115,234,
    +	197,94,253,16,144,151,41>>
     	5>

    The [<<"First bytes">>,<<"Second bytes">>] could of course have been one single binary: <<"First bytesSecond bytes">>.

    Example of crypto_one_time_aead/6

    The same example as in the previous section, but now with one -call to crypto_one_time_aead/6:

    	1> Key = <<1:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    -	2> IV = <<0:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
    -	3> Txt = [<<"First bytes">>,<<"Second bytes">>].
    -	[<<"First bytes">>,<<"Second bytes">>]
    -	4> AAD = <<"Some additional auth data">>.
    -	<<"Some additional auth data">>
    -	5> crypto:crypto_one_time_aead(aes_128_gcm, Key, IV, Txt, AAD, true).
    -	{<<240,130,38,96,130,241,189,52,3,190,179,213,132,1,72,
    -	192,103,176,90,104,15,71,158>>,
    -	<<131,47,45,91,142,85,9,244,21,141,214,71,31,135,2,155>>}
    +call to crypto_one_time_aead/6:

    	1> Key = <<1:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    +	2> IV = <<0:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
    +	3> Txt = [<<"First bytes">>,<<"Second bytes">>].
    +	[<<"First bytes">>,<<"Second bytes">>]
    +	4> AAD = <<"Some additional auth data">>.
    +	<<"Some additional auth data">>
    +	5> crypto:crypto_one_time_aead(aes_128_gcm, Key, IV, Txt, AAD, true).
    +	{<<240,130,38,96,130,241,189,52,3,190,179,213,132,1,72,
    +	192,103,176,90,104,15,71,158>>,
    +	<<131,47,45,91,142,85,9,244,21,141,214,71,31,135,2,155>>}
     	6>

    The [<<"First bytes">>,<<"Second bytes">>] could of course have been one -single binary: <<"First bytesSecond bytes">>.

    Example of mac_init mac_update and mac_final

    	1> Key = <<1:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    -	2> StateMac = crypto:mac_init(cmac, aes_128_cbc, Key).
    +single binary: <<"First bytesSecond bytes">>.

    Example of mac_init mac_update and mac_final

    	1> Key = <<1:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    +	2> StateMac = crypto:mac_init(cmac, aes_128_cbc, Key).
     	#Ref<0.2424664121.2781478916.232610>
    -	3> crypto:mac_update(StateMac, <<"First bytes">>).
    +	3> crypto:mac_update(StateMac, <<"First bytes">>).
     	#Ref<0.2424664121.2781478916.232610>
    -	4> crypto:mac_update(StateMac, " ").
    +	4> crypto:mac_update(StateMac, " ").
     	#Ref<0.2424664121.2781478916.232610>
    -	5> crypto:mac_update(StateMac, <<"last bytes">>).
    +	5> crypto:mac_update(StateMac, <<"last bytes">>).
     	#Ref<0.2424664121.2781478916.232610>
    -	6> crypto:mac_final(StateMac).
    -	<<68,191,219,128,84,77,11,193,197,238,107,6,214,141,160,
    -	249>>
    -	7>

    and compare the result with a single calculation just for this example:

    	7> crypto:mac(cmac, aes_128_cbc, Key, "First bytes last bytes").
    -	<<68,191,219,128,84,77,11,193,197,238,107,6,214,141,160,
    -	249>>
    -	8> v(7) == v(6).
    +	6> crypto:mac_final(StateMac).
    +	<<68,191,219,128,84,77,11,193,197,238,107,6,214,141,160,
    +	249>>
    +	7>

    and compare the result with a single calculation just for this example:

    	7> crypto:mac(cmac, aes_128_cbc, Key, "First bytes last bytes").
    +	<<68,191,219,128,84,77,11,193,197,238,107,6,214,141,160,
    +	249>>
    +	8> v(7) == v(6).
     	true
     	9>

    Retired cipher names

    This table lists the retired cipher names in the first column and suggests names to replace them with in the second column.

    The new names follows the OpenSSL libcrypto names. The format is /usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1823)) --- old//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.html 2026-08-21 04:00:20.006298556 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/crypto.html 2026-08-21 04:00:20.014298608 +0000 @@ -3813,7 +3813,7 @@ -

    rsa_public() = [E, N]
    rsa_private() = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]

    Where E is the public exponent, N is public modulus and D is the private +

    rsa_public() = [E, N]
    rsa_private() = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]

    Where E is the public exponent, N is public modulus and D is the private exponent. The longer key format contains redundant information that will make the calculation faster. P1 and P2 are first and second prime factors. E1 and E2 are first and second exponents. C is the CRT coefficient. The terminology is @@ -6687,9 +6687,9 @@

    Create a generator for rand and save it in the process dictionary.

    Equivalent to rand_seed_s/0 but also saves the returned state object (generator) in the process dictionary. That is, -it is equivalent to rand:seed(rand_seed_s()).

    See rand:seed/1 and rand_seed_s/0.

    Example

    _ = crypto:rand_seed(),
    -IntegerValue = rand:uniform(42), % 1 .. 42
    -FloatValue = rand:uniform().     % [0.0; 1.0)

    Note

    Note that when using the process dictionary for cryptographically +it is equivalent to rand:seed(rand_seed_s()).

    See rand:seed/1 and rand_seed_s/0.

    Example

    _ = crypto:rand_seed(),
    +IntegerValue = rand:uniform(42), % 1 .. 42
    +FloatValue = rand:uniform().     % [0.0; 1.0)

    Note

    Note that when using the process dictionary for cryptographically secure random numbers one has to ensure that no code called between initializing the generator and between generating numbers accidentally alters the generator state in the process dictionary.

    The safe approach is to use the rand functions that @@ -6729,9 +6729,9 @@ and save it in the process dictionary.

    Equivalent rand_seed_alg_s/1 but also saves the returned state object (generator) in the process dictionary. That is, it is equivalent to rand:seed(rand_seed_alg_s(Alg)).

    See rand:seed/1 and rand_seed_alg_s/1. -Note the warning about the usage of the process dictionary in rand_seed/0.

    Example

    _ = crypto:rand_seed_alg(crypto_cache),
    -IntegerValue = rand:uniform(42), % 1 .. 42
    -FloatValue = rand:uniform().     % [0.0; 1.0)
    +Note the warning about the usage of the process dictionary in rand_seed/0.

    Example

    _ = crypto:rand_seed_alg(crypto_cache),
    +IntegerValue = rand:uniform(42), % 1 .. 42
    +FloatValue = rand:uniform().     % [0.0; 1.0)
    @@ -6766,12 +6766,12 @@ and save it in the process dictionary.

    Equivalent to rand_seed_alg_s/2 but also saves the returned state object (generator) in the process dictionary. That is, it is equivalent to rand:seed(rand_seed_alg_s(Alg, Seed)).

    See rand:seed/1 and rand_seed_alg_s/2. -Note the warning about the usage of the process dictionary in rand_seed/0.

    Example

    _ = crypto:rand_seed_alg(crypto_aes, "my seed"),
    -IntegerValue = rand:uniform(42), % 1 .. 42
    -FloatValue = rand:uniform(),     % [0.0; 1.0)
    -_ = crypto:rand_seed_alg(crypto_aes, "my seed"),
    -IntegerValue = rand:uniform(42), % Same values
    -FloatValue = rand:uniform().     % again
    +Note the warning about the usage of the process dictionary in rand_seed/0.

    Example

    _ = crypto:rand_seed_alg(crypto_aes, "my seed"),
    +IntegerValue = rand:uniform(42), % 1 .. 42
    +FloatValue = rand:uniform(),     % [0.0; 1.0)
    +_ = crypto:rand_seed_alg(crypto_aes, "my seed"),
    +IntegerValue = rand:uniform(42), % Same values
    +FloatValue = rand:uniform().     % again
    @@ -6805,9 +6805,9 @@ which when used by the rand functions produce cryptographically strong random number.

    See also rand:seed_s/1 and for example rand:uniform_s/2.

    If Alg is crypto this function is equivalent to rand_seed_s/0.

    If Alg is crypto_cache the returned generator fetches random data with OpenSSL's RAND_bytes and caches it as 56 bit numbers -which makes calculations fast on 64 bit machines.

    Example

    S0 = crypto:rand_seed_alg_s(crypto_cache),
    -{IntegerValue, S1} = rand:uniform(42, S0), % 1 .. 42
    -{FloatValue, S2} = rand:uniform(S1).       % [0.0; 1.0)

    May cause the rand functions using this state object +which makes calculations fast on 64 bit machines.

    Example

    S0 = crypto:rand_seed_alg_s(crypto_cache),
    +{IntegerValue, S1} = rand:uniform(42, S0), % 1 .. 42
    +{FloatValue, S2} = rand:uniform(S1).       % [0.0; 1.0)

    May cause the rand functions using this state object to raise the exception error:low_entropy in case the random generator failed due to lack of secure "randomness".

    The cache size can be changed from its default value using the crypto app's configuration parameter rand_cache_size.

    Note

    The state returned from this function cannot be used to get a reproducible @@ -6856,12 +6856,12 @@ for the same seed.

    • If you need cryptographically strong random numbers use rand_seed_alg_s/1 with Alg =:= crypto or Alg =:= crypto_cache.
    • If you need to be able to repeat the sequence use this function with Alg =:= crypto_aes.
    • If you do not need the statistical quality of this function, there are faster -algorithms in the rand module.

    Example

    S0 = crypto:rand_seed_alg_s(crypto_aes, "my seed"),
    -{IntegerValue, S1} = rand:uniform(42, S0), % 1 .. 42
    -{FloatValue, S2 = rand:uniform(S1),        % [0.0; 1.0)
    -S3 = crypto:rand_seed_alg_s(crypto_aes, "my seed"),
    -{IntegerValue, S4} = rand:uniform(42, S3), % Same values
    -{FloatValue, S5} = rand:uniform(S4).       % again

    Thanks to the used generator the state object supports the +algorithms in the rand module.

    Example

    S0 = crypto:rand_seed_alg_s(crypto_aes, "my seed"),
    +{IntegerValue, S1} = rand:uniform(42, S0), % 1 .. 42
    +{FloatValue, S2 = rand:uniform(S1),        % [0.0; 1.0)
    +S3 = crypto:rand_seed_alg_s(crypto_aes, "my seed"),
    +{IntegerValue, S4} = rand:uniform(42, S3), % Same values
    +{FloatValue, S5} = rand:uniform(S4).       % again

    Thanks to the used generator the state object supports the rand:jump/0,1 function with distance 2^512.

    Numbers are generated in batches and cached for speed reasons. The cache size can be changed from its default value using the crypto app's configuration parameter rand_cache_size.

    @@ -6898,8 +6898,8 @@ which when used by the rand functions produce cryptographically strong random numbers (based on OpenSSL's BN_rand_range function). See also rand:seed_s/1, and for example -rand:uniform_s/2.

    Example

    S0 = crypto:rand_seed_s(),
    -{RandomInteger, S1} = rand:uniform_s(1000, S0).

    May cause the rand functions using this state object +rand:uniform_s/2.

    Example

    S0 = crypto:rand_seed_s(),
    +{RandomInteger, S1} = rand:uniform_s(1000, S0).

    May cause the rand functions using this state object to raise the exception error:low_entropy in case the random generator failed due to lack of secure "randomness".

    Note

    The state returned from this function cannot be used to get a reproducible random sequence as from the other rand functions, since that would @@ -7527,14 +7527,14 @@ -

    Get information about crypto and the OpenSSL backend.

    Returns a map with information about the compilation and linking of crypto.

    Example:

    1> crypto:info().
    -#{compile_type => normal,
    +

    Get information about crypto and the OpenSSL backend.

    Returns a map with information about the compilation and linking of crypto.

    Example:

    1> crypto:info().
    +#{compile_type => normal,
       cryptolib_version_compiled => "OpenSSL 3.0.0 7 sep 2021",
       cryptolib_version_linked => "OpenSSL 3.0.0 7 sep 2021",
       link_type => dynamic,
       otp_crypto_version => "5.0.2",
       fips_provider_available => true,
    -  fips_provider_buildinfo => "3.0.0"}
    +  fips_provider_buildinfo => "3.0.0"}
     2>

    More association types than documented may be present in the map. Some of the associations (like fips) may be absent if not supported.

    @@ -7603,8 +7603,8 @@

    Get the name and version of the libraries used by crypto.

    Name is the name of the library. VerNum is the numeric version according to the library's own versioning scheme. VerStr contains a text variant of the -version.

    > info_lib().
    -[{<<"OpenSSL">>,269484095,<<"OpenSSL 1.1.0c  10 Nov 2016"">>}]

    Note

    From OTP R16 the numeric version represents the version of the OpenSSL +version.

    > info_lib().
    +[{<<"OpenSSL">>,269484095,<<"OpenSSL 1.1.0c  10 Nov 2016"">>}]

    Note

    From OTP R16 the numeric version represents the version of the OpenSSL header files (openssl/opensslv.h) used when crypto was compiled. The text variant represents the libcrypto library used at runtime. In earlier OTP versions both numeric and text was taken from the library.

    /usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/engine_keys.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1130)) --- old//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/engine_keys.html 2026-08-21 04:00:20.034298738 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/engine_keys.html 2026-08-21 04:00:20.034298738 +0000 @@ -107,30 +107,30 @@ string or binary and depends on the Engine loaded
  • an Erlang map is constructed with the Engine reference, the key reference and possibly a key passphrase if needed by the Engine. See the Reference Manual for details of the map.
  • Use Cases

    Sign with an engine stored private key

    This example shows how to construct a key reference that is used in a sign -operation. The actual key is stored in the engine that is loaded at prompt 1.

    1> {ok, EngineRef} = crypto:engine_load(....).
    +operation. The actual key is stored in the engine that is loaded at prompt 1.

    1> {ok, EngineRef} = crypto:engine_load(....).
     ...
    -{ok,#Ref<0.2399045421.3028942852.173962>}
    -2> PrivKey = #{engine => EngineRef,
    -               key_id => "id of the private key in Engine"}.
    +{ok,#Ref<0.2399045421.3028942852.173962>}
    +2> PrivKey = #{engine => EngineRef,
    +               key_id => "id of the private key in Engine"}.
     ...
    -3> Signature = crypto:sign(rsa, sha, <<"The message">>, PrivKey).
    -<<65,6,125,254,54,233,84,77,83,63,168,28,169,214,121,76,
    -  207,177,124,183,156,185,160,243,36,79,125,230,231,...>>

    Verify with an engine stored public key

    Here the signature and message in the last example is verifyed using the public +3> Signature = crypto:sign(rsa, sha, <<"The message">>, PrivKey). +<<65,6,125,254,54,233,84,77,83,63,168,28,169,214,121,76, + 207,177,124,183,156,185,160,243,36,79,125,230,231,...>>

    Verify with an engine stored public key

    Here the signature and message in the last example is verifyed using the public key. The public key is stored in an engine, only to exemplify that it is -possible. The public key could of course be handled openly as usual.

    4> PublicKey = #{engine => EngineRef,
    -                 key_id => "id of the public key in Engine"}.
    +possible. The public key could of course be handled openly as usual.

    4> PublicKey = #{engine => EngineRef,
    +                 key_id => "id of the public key in Engine"}.
     ...
    -5> crypto:verify(rsa, sha, <<"The message">>, Signature, PublicKey).
    +5> crypto:verify(rsa, sha, <<"The message">>, Signature, PublicKey).
     true
     6>

    Using a password protected private key

    The same example as the first sign example, except that a password protects the -key down in the Engine.

    6> PrivKeyPwd = #{engine => EngineRef,
    +key down in the Engine.

    6> PrivKeyPwd = #{engine => EngineRef,
                       key_id => "id of the pwd protected private key in Engine",
    -		  password => "password"}.
    +		  password => "password"}.
     ...
    -7> crypto:sign(rsa, sha, <<"The message">>, PrivKeyPwd).
    -<<140,80,168,101,234,211,146,183,231,190,160,82,85,163,
    +7> crypto:sign(rsa, sha, <<"The message">>, PrivKeyPwd).
    +<<140,80,168,101,234,211,146,183,231,190,160,82,85,163,
       175,106,77,241,141,120,72,149,181,181,194,154,175,76,
    -  223,...>>
    +  223,...>>
     8>
    /usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/engine_load.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1099)) --- old//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/engine_load.html 2026-08-21 04:00:20.054298869 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/engine_load.html 2026-08-21 04:00:20.054298869 +0000 @@ -98,32 +98,32 @@ performance over its software-based counterpart, which is known as cryptographic acceleration.

    Note

    The file name requirement on the engine dynamic library can differ between SSL versions.

    Use Cases

    Dynamically load an engine from default directory

    If the engine is located in the OpenSSL/LibreSSL installation engines -directory.

    1> {ok, Engine} = crypto:engine_load(<<"otp_test_engine">>, [], []).
    - {ok, #Ref}

    Load an engine with the dynamic engine

    Load an engine with the help of the dynamic engine by giving the path to the -library.

     2> {ok, Engine} = crypto:engine_load(<<"dynamic">>,
    -                                      [{<<"SO_PATH">>,
    -                                        <<"/some/path/otp_test_engine.so">>},
    -                                       {<<"ID">>, <<"MD5">>},
    -                                       <<"LOAD">>],
    -                                      []).
    - {ok, #Ref}

    Load an engine and replace some methods

    Load an engine with the help of the dynamic engine and just replace some engine -methods.

     3> {ok, Engine} = crypto:engine_load(<<"dynamic">>,
    -                                      [{<<"SO_PATH">>,
    -                                        <<"/some/path/otp_test_engine.so">>},
    -                                       {<<"ID">>, <<"MD5">>},
    -                                       <<"LOAD">>],
    -                                      []).
    -{ok, #Ref}
    -4> ok = crypto:engine_register(Engine, [engine_method_digests]).
    +directory.

    1> {ok, Engine} = crypto:engine_load(<<"otp_test_engine">>, [], []).
    + {ok, #Ref}

    Load an engine with the dynamic engine

    Load an engine with the help of the dynamic engine by giving the path to the +library.

     2> {ok, Engine} = crypto:engine_load(<<"dynamic">>,
    +                                      [{<<"SO_PATH">>,
    +                                        <<"/some/path/otp_test_engine.so">>},
    +                                       {<<"ID">>, <<"MD5">>},
    +                                       <<"LOAD">>],
    +                                      []).
    + {ok, #Ref}

    Load an engine and replace some methods

    Load an engine with the help of the dynamic engine and just replace some engine +methods.

     3> {ok, Engine} = crypto:engine_load(<<"dynamic">>,
    +                                      [{<<"SO_PATH">>,
    +                                        <<"/some/path/otp_test_engine.so">>},
    +                                       {<<"ID">>, <<"MD5">>},
    +                                       <<"LOAD">>],
    +                                      []).
    +{ok, #Ref}
    +4> ok = crypto:engine_register(Engine, [engine_method_digests]).
     ok

    Load with the ensure loaded function

    This function makes sure the engine is loaded just once and the ID is added to the internal engine list of OpenSSL. The following calls to the function will -check if the ID is loaded and then just get a new reference to the engine.

     5> {ok, Engine} = crypto:ensure_engine_loaded(<<"MD5">>,
    -                                               <<"/some/path/otp_test_engine.so">>).
    - {ok, #Ref}

    To remove the tag from the OpenSSL engine list use crypto:engine_remove/1.

     6> crypto:engine_remove(Engine).
    +check if the ID is loaded and then just get a new reference to the engine.

     5> {ok, Engine} = crypto:ensure_engine_loaded(<<"MD5">>,
    +                                               <<"/some/path/otp_test_engine.so">>).
    + {ok, #Ref}

    To remove the tag from the OpenSSL engine list use crypto:engine_remove/1.

     6> crypto:engine_remove(Engine).
      ok

    To unload it use crypto:engine_unload/1 which removes the references to the -engine.

     6> crypto:engine_unload(Engine).
    - ok

    List all engines currently loaded

     8> crypto:engine_list().
    -[<<"dynamic">>, <<"MD5">>]
    +engine.

     6> crypto:engine_unload(Engine).
    + ok

    List all engines currently loaded

     8> crypto:engine_list().
    +[<<"dynamic">>, <<"MD5">>]
    /usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/new_api.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2413)) --- old//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/new_api.html 2026-08-21 04:00:20.074298999 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/crypto-5.8.3.2/doc/html/new_api.html 2026-08-21 04:00:20.074298999 +0000 @@ -114,85 +114,85 @@ initialises the crypto context. One or more calls crypto_update/2 does the actual encryption or decryption for each block.

    This example shows first the encryption of two blocks and then decryptions of the cipher text, but divided into three blocks just to show that it is possible -to divide the plain text and cipher text differently for some ciphers:

    	1> application:start(crypto).
    +to divide the plain text and cipher text differently for some ciphers:

    	1> application:start(crypto).
     	ok
    -	2> Key = <<1:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    -	3> IV = <<0:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
    -	4> StateEnc = crypto:crypto_init(aes_128_ctr, Key, IV, true). % encrypt -> true
    +	2> Key = <<1:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    +	3> IV = <<0:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
    +	4> StateEnc = crypto:crypto_init(aes_128_ctr, Key, IV, true). % encrypt -> true
     	#Ref<0.3768901617.1128660993.124047>
    -	5> crypto:crypto_update(StateEnc, <<"First bytes">>).
    -	<<67,44,216,166,25,130,203,5,66,6,162>>
    -	6> crypto:crypto_update(StateEnc, <<"Second bytes">>).
    -	<<16,79,94,115,234,197,94,253,16,144,151,41>>
    +	5> crypto:crypto_update(StateEnc, <<"First bytes">>).
    +	<<67,44,216,166,25,130,203,5,66,6,162>>
    +	6> crypto:crypto_update(StateEnc, <<"Second bytes">>).
    +	<<16,79,94,115,234,197,94,253,16,144,151,41>>
     	7>
    -	7> StateDec = crypto:crypto_init(aes_128_ctr, Key, IV, false). % decrypt -> false
    +	7> StateDec = crypto:crypto_init(aes_128_ctr, Key, IV, false). % decrypt -> false
     	#Ref<0.3768901617.1128660994.124255>
    -	8> crypto:crypto_update(StateDec, <<67,44,216,166,25,130,203>>).
    -	<<"First b">>
    -	9> crypto:crypto_update(StateDec, <<5,66,6,162,16,79,94,115,234,197,
    -        94,253,16,144,151>>).
    -	<<"ytesSecond byte">>
    -	10> crypto:crypto_update(StateDec, <<41>>).
    -	<<"s">>
    +	8> crypto:crypto_update(StateDec, <<67,44,216,166,25,130,203>>).
    +	<<"First b">>
    +	9> crypto:crypto_update(StateDec, <<5,66,6,162,16,79,94,115,234,197,
    +        94,253,16,144,151>>).
    +	<<"ytesSecond byte">>
    +	10> crypto:crypto_update(StateDec, <<41>>).
    +	<<"s">>
     	11>

    Note that the internal data that the StateEnc and StateDec references are destructivly updated by the calls to crypto_update/2. This is to gain time in the calls of the nifs interfacing the cryptolib. In a loop where the state is saved in the loop's state, it also saves one update of the loop state per crypto operation.

    For example, a simple server receiving text parts to encrypt and send the result -back to the one who sent them (the Requester):

    	encode(Crypto, Key, IV) ->
    -	crypto_loop(crypto:crypto_init(Crypto, Key, IV, true)).
    +back to the one who sent them (the Requester):

    	encode(Crypto, Key, IV) ->
    +	crypto_loop(crypto:crypto_init(Crypto, Key, IV, true)).
     
    -	crypto_loop(State) ->
    +	crypto_loop(State) ->
     	receive
    -        {Text, Requester} ->
    -        Requester ! crypto:crypto_update(State, Text),
    -	loop(State)
    +        {Text, Requester} ->
    +        Requester ! crypto:crypto_update(State, Text),
    +	loop(State)
     	end.

    Example of crypto_one_time/5

    The same example as in the previous section, -but now with one call to crypto_one_time/5:

    	1> Key = <<1:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    -	2> IV = <<0:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
    -	3> Txt = [<<"First bytes">>,<<"Second bytes">>].
    -	[<<"First bytes">>,<<"Second bytes">>]
    -	4> crypto:crypto_one_time(aes_128_ctr, Key, IV, Txt, true).
    -	<<67,44,216,166,25,130,203,5,66,6,162,16,79,94,115,234,
    -	197,94,253,16,144,151,41>>
    +but now with one call to crypto_one_time/5:

    	1> Key = <<1:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    +	2> IV = <<0:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
    +	3> Txt = [<<"First bytes">>,<<"Second bytes">>].
    +	[<<"First bytes">>,<<"Second bytes">>]
    +	4> crypto:crypto_one_time(aes_128_ctr, Key, IV, Txt, true).
    +	<<67,44,216,166,25,130,203,5,66,6,162,16,79,94,115,234,
    +	197,94,253,16,144,151,41>>
     	5>

    The [<<"First bytes">>,<<"Second bytes">>] could of course have been one single binary: <<"First bytesSecond bytes">>.

    Example of crypto_one_time_aead/6

    The same example as in the previous section, but now with one -call to crypto_one_time_aead/6:

    	1> Key = <<1:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    -	2> IV = <<0:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
    -	3> Txt = [<<"First bytes">>,<<"Second bytes">>].
    -	[<<"First bytes">>,<<"Second bytes">>]
    -	4> AAD = <<"Some additional auth data">>.
    -	<<"Some additional auth data">>
    -	5> crypto:crypto_one_time_aead(aes_128_gcm, Key, IV, Txt, AAD, true).
    -	{<<240,130,38,96,130,241,189,52,3,190,179,213,132,1,72,
    -	192,103,176,90,104,15,71,158>>,
    -	<<131,47,45,91,142,85,9,244,21,141,214,71,31,135,2,155>>}
    +call to crypto_one_time_aead/6:

    	1> Key = <<1:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    +	2> IV = <<0:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>
    +	3> Txt = [<<"First bytes">>,<<"Second bytes">>].
    +	[<<"First bytes">>,<<"Second bytes">>]
    +	4> AAD = <<"Some additional auth data">>.
    +	<<"Some additional auth data">>
    +	5> crypto:crypto_one_time_aead(aes_128_gcm, Key, IV, Txt, AAD, true).
    +	{<<240,130,38,96,130,241,189,52,3,190,179,213,132,1,72,
    +	192,103,176,90,104,15,71,158>>,
    +	<<131,47,45,91,142,85,9,244,21,141,214,71,31,135,2,155>>}
     	6>

    The [<<"First bytes">>,<<"Second bytes">>] could of course have been one -single binary: <<"First bytesSecond bytes">>.

    Example of mac_init mac_update and mac_final

    	1> Key = <<1:128>>.
    -	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    -	2> StateMac = crypto:mac_init(cmac, aes_128_cbc, Key).
    +single binary: <<"First bytesSecond bytes">>.

    Example of mac_init mac_update and mac_final

    	1> Key = <<1:128>>.
    +	<<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>>
    +	2> StateMac = crypto:mac_init(cmac, aes_128_cbc, Key).
     	#Ref<0.2424664121.2781478916.232610>
    -	3> crypto:mac_update(StateMac, <<"First bytes">>).
    +	3> crypto:mac_update(StateMac, <<"First bytes">>).
     	#Ref<0.2424664121.2781478916.232610>
    -	4> crypto:mac_update(StateMac, " ").
    +	4> crypto:mac_update(StateMac, " ").
     	#Ref<0.2424664121.2781478916.232610>
    -	5> crypto:mac_update(StateMac, <<"last bytes">>).
    +	5> crypto:mac_update(StateMac, <<"last bytes">>).
     	#Ref<0.2424664121.2781478916.232610>
    -	6> crypto:mac_final(StateMac).
    -	<<68,191,219,128,84,77,11,193,197,238,107,6,214,141,160,
    -	249>>
    -	7>

    and compare the result with a single calculation just for this example:

    	7> crypto:mac(cmac, aes_128_cbc, Key, "First bytes last bytes").
    -	<<68,191,219,128,84,77,11,193,197,238,107,6,214,141,160,
    -	249>>
    -	8> v(7) == v(6).
    +	6> crypto:mac_final(StateMac).
    +	<<68,191,219,128,84,77,11,193,197,238,107,6,214,141,160,
    +	249>>
    +	7>

    and compare the result with a single calculation just for this example:

    	7> crypto:mac(cmac, aes_128_cbc, Key, "First bytes last bytes").
    +	<<68,191,219,128,84,77,11,193,197,238,107,6,214,141,160,
    +	249>>
    +	8> v(7) == v(6).
     	true
     	9>

    Retired cipher names

    This table lists the retired cipher names in the first column and suggests names to replace them with in the second column.

    The new names follows the OpenSSL libcrypto names. The format is /usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> debugger - 6.0.3 - urn:uuid:f905ee15-67d0-7522-b843-8704da447210 + urn:uuid:2b44bf2b-800c-84bb-dead-fac4466f026e en - 2026-08-21T03:49:22Z + 2042-09-22T17:08:20Z /usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/debugger_chapter.xhtml differs (HTML document, ASCII text, with very long lines (1407)) --- old//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/debugger_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/debugger_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -38,12 +38,12 @@ window, View Module window, or Attach Process window.

    Executable Lines

    To have an effect, a breakpoint must be set at an executable line, which is a line of code containing an executable expression such as a matching or a function call. A blank line or a line containing a comment, function head, or -pattern in a case statement or receive statement is not executable.

    In the following example, lines 2, 4, 6, 8, and 11 are executable lines:

    1: is_loaded(Module,Compiled) ->
    -2:   case get_file(Module,Compiled) of
    -3:     {ok,File} ->
    -4:       case code:which(Module) of
    +pattern in a case statement or receive statement is not executable.

    In the following example, lines 2, 4, 6, 8, and 11 are executable lines:

    1: is_loaded(Module,Compiled) ->
    +2:   case get_file(Module,Compiled) of
    +3:     {ok,File} ->
    +4:       case code:which(Module) of
     5:         ?TAG ->
    -6:           {loaded,File};
    +6:           {loaded,File};
     7:         _ ->
     8:           unloaded
     9:       end;
    @@ -64,13 +64,13 @@
     returns unbound or {value,Value}.

    Conditional Break Dialog Window

    Right-click the Module entry to open a popup menu from which the appropriate module can be selected.

    Example:

    A conditional breakpoint calling c_test:c_break/1 is added at line 6 in module fact. Each time the breakpoint is reached, the function is called. When N is -equal to 3, the function returns true and the process stops.

    Extract from fact.erl:

    5. fac(0) -> 1;
    -6. fac(N) when N > 0, is_integer(N) -> N * fac(N-1).

    Definition of c_test:c_break/1:

    -module(c_test).
    --export([c_break/1]).
    +equal to 3, the function returns true and the process stops.

    Extract from fact.erl:

    5. fac(0) -> 1;
    +6. fac(N) when N > 0, is_integer(N) -> N * fac(N-1).

    Definition of c_test:c_break/1:

    -module(c_test).
    +-export([c_break/1]).
     
    -c_break(Bindings) ->
    -    case int:get_binding('N', Bindings) of
    -        {value, 3} ->
    +c_break(Bindings) ->
    +    case int:get_binding('N', Bindings) of
    +        {value, 3} ->
                 true;
             _ ->
                 false
    @@ -79,12 +79,12 @@
     right-click the Module entry.

    To bring up all functions of the module in the listbox, click the OK button (or press the Return or Tab key) when a module name has been specified,.

    Stack Trace

    The Erlang emulator keeps track of a stack trace, information about recent function calls. This information is used if an error occurs, for example:

    1> catch a+1.
    -{'EXIT',{badarith,[{erlang,'+',[a,1],[]},
    -                   {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,573}]},
    -                   {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,357}]},
    -                   {shell,exprs,7,[{file,"shell.erl"},{line,674}]},
    -                   {shell,eval_exprs,7,[{file,"shell.erl"},{line,629}]},
    -                   {shell,eval_loop,3,[{file,"shell.erl"},{line,614}]}]}}

    For details about the stack trace, see section +{'EXIT',{badarith,[{erlang,'+',[a,1],[]}, + {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,573}]}, + {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,357}]}, + {shell,exprs,7,[{file,"shell.erl"},{line,674}]}, + {shell,eval_exprs,7,[{file,"shell.erl"},{line,629}]}, + {shell,eval_loop,3,[{file,"shell.erl"},{line,614}]}]}}

    For details about the stack trace, see section Errors and Error Handling in the Erlang Reference Manual.

    Debugger emulates the stack trace by keeping track of recently called interpreted functions. (The real stack trace cannot be used, as it shows which /usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/int.xhtml differs (HTML document, ASCII text, with very long lines (962)) --- old//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/int.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/int.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -563,7 +563,7 @@

    Sets when and how to attach automatically to a process executing code in interpreted modules.

    By default when the interpreter is started, automatic attach is disabled.

    If Flags is an empty list, automatic attach is disabled.

    Otherwise Flags should be a list containing at least one of the following flags:

    • init - Attach when a process for the first time calls an interpreted -function.
    • break - Attach whenever a process reaches a breakpoint.
    • exit - Attach when a process terminates.

    When the specified event occurs, the function Function is called as:

    spawn(Module, Name, [Pid | Args])

    Pid is the pid of the process executing interpreted code.

    +function.
  • break - Attach whenever a process reaches a breakpoint.
  • exit - Attach when a process terminates.
  • When the specified event occurs, the function Function is called as:

    spawn(Module, Name, [Pid | Args])

    Pid is the pid of the process executing interpreted code.

    /usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/i.xhtml differs (HTML document, ASCII text, with very long lines (424)) --- old//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/i.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/i.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -28,9 +28,9 @@ interpreted processes and break points.

    It is possible to attach to interpreted processes by only giving the corresponding process identity. By default, an attachment window is displayed. Processes at other Erlang nodes can be attached manually or automatically.

    The functions in this module are defined in the Erlang shell. That is, -they can be called without the i: prefix. For example:

    1> ii(t).
    -{module,t}
    -2> iaa([init]).
    +they can be called without the i: prefix. For example:

    1> ii(t).
    +{module,t}
    +2> iaa([init]).
     true
    /usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/notes.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (3908)) --- old//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -17,24 +17,24 @@

    Debugger Release Notes

    -

    This document describes the changes made to the Debugger application.

    Debugger 6.0.3

    Fixed Bugs and Malfunctions

    • Fixed unbound error in interpreted modules

      Own Id: OTP-19719 Aux Id: GH-10057, PR-10066

    Debugger 6.0.2

    Fixed Bugs and Malfunctions

    • Fixed debugger priv dir, which was removed and caused crashes when the icons could not be found.

      Own Id: OTP-19687 Aux Id: PR-9994, GH-9858

    Debugger 6.0.1

    Fixed Bugs and Malfunctions

    • Restore deleted icon so that debugger does not crash on startup.

      Own Id: OTP-19641 Aux Id: GH-9858, PR-9861

    Debugger 6.0

    Fixed Bugs and Malfunctions

    • Error handling has been improved when modules fail to load.

      Own Id: OTP-19484 Aux Id: GH-7819, PR-9399

    Improvements and New Features

    • Comprehensions have been extended with zip generators according to EEP 73.

      Example:

      1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
      -[5,7,9]

      Own Id: OTP-19184 Aux Id: PR-8926

    • New strict generators have been added for comprehensions.

      The currently existing generators are "relaxed": they ignore terms in the +

      This document describes the changes made to the Debugger application.

      Debugger 6.0.3

      Fixed Bugs and Malfunctions

      • Fixed unbound error in interpreted modules

        Own Id: OTP-19719 Aux Id: GH-10057, PR-10066

      Debugger 6.0.2

      Fixed Bugs and Malfunctions

      • Fixed debugger priv dir, which was removed and caused crashes when the icons could not be found.

        Own Id: OTP-19687 Aux Id: PR-9994, GH-9858

      Debugger 6.0.1

      Fixed Bugs and Malfunctions

      • Restore deleted icon so that debugger does not crash on startup.

        Own Id: OTP-19641 Aux Id: GH-9858, PR-9861

      Debugger 6.0

      Fixed Bugs and Malfunctions

      • Error handling has been improved when modules fail to load.

        Own Id: OTP-19484 Aux Id: GH-7819, PR-9399

      Improvements and New Features

      • Comprehensions have been extended with zip generators according to EEP 73.

        Example:

        1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
        +[5,7,9]

        Own Id: OTP-19184 Aux Id: PR-8926

      • New strict generators have been added for comprehensions.

        The currently existing generators are "relaxed": they ignore terms in the right-hand side expression that do not match the left-hand side pattern.

        The new strict generators fail with exception badmatch if a pattern doesn't match.

        Examples:

        Using the current relaxed generator operator <-, any element not matching -the pattern {_,_} will be silently discarded:

        1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
        -[{ok,1},{error,2}]

        If the intention is that all lists processed by a list comprehension must only +the pattern {_,_} will be silently discarded:

        1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
        +[{ok,1},{error,2}]

        If the intention is that all lists processed by a list comprehension must only contain tuples of size two, using the new strict version of the operator ensures -that term not matching will cause a crash:

        2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
        +that term not matching will cause a crash:

        2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
         ** exception error: no match of right hand side value ok

        Using the strict generator operator to mark the intention that all list elements must match the pattern could help finding mistakes quicker if something unpexected is added to the list processed by the generator.

        The strict version for bitstring generators is <:=.

        Own Id: OTP-19317 Aux Id: PR-8625

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      Debugger 5.5.0.1

      Fixed Bugs and Malfunctions

      • Fix unbound error in interpreted modules

        Own Id: OTP-19719 Aux Id: GH-10057, PR-10066

      Debugger 5.5

      Fixed Bugs and Malfunctions

      • Defining a fun in the shell using the syntax fun Name/Arity would fail. This has been corrected so that the following now works:

        1> F = fun is_atom/1.
         #Fun.erl.42.18682967>
        -> F(a).
        +> F(a).
         true
         3> Id = fun id/1.
         #Fun.erl.42.18682967>
        -4> Id(42).
        +4> Id(42).
         ** exception error: undefined shell command id/1
        -5> id(I) -> I.
        +5> id(I) -> I.
         ok
        -6> Id(42).
        +6> Id(42).
         42

        The Debugger has also been corrected to correctly handle this syntax for a BIF.

        Own Id: OTP-19322 Aux Id: GH-8963, PR-8987

      Improvements and New Features

      • Erlang/OTP type specifications has been updated to eliminate overlapping domains.

        Own Id: OTP-19310 Aux Id: GH-8810, GH-8821, PR-8986

      Debugger 5.4

      Fixed Bugs and Malfunctions

      • The dependencies for this application are now listed in the app file.

        Own Id: OTP-18831 Aux Id: PR-7441

      Improvements and New Features

      • Type specs have been added to all API functions.

        Own Id: OTP-18819 Aux Id: PR-7781

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      • The Debugger now use a trace session for its internal use of tracing to avoid interfering with the user's use of tracing.

        Own Id: OTP-19074 Aux Id: PR-8389

      Debugger 5.3.4

      Fixed Bugs and Malfunctions

      • Guards with nested record expression could wrongly evaluate to false.

        Own Id: OTP-18958 Aux Id: GH-8120, PR-8275

      Debugger 5.3.3

      Fixed Bugs and Malfunctions

      • Map comprehensions now work in the Debugger.

        Own Id: OTP-18888 Aux Id: GH-7914

      Debugger 5.3.2

      Fixed Bugs and Malfunctions

      • The call int:no_break(Module) did not remove any breakpoints.

        Own Id: OTP-18644 Aux Id: GH-7336

      • The maybe expression is now supported in the Debugger.

        Own Id: OTP-18740 Aux Id: GH-7410, PR-7599

      Debugger 5.3.1.3

      Fixed Bugs and Malfunctions

      • Guards with nested record expression could wrongly evaluate to false.

        Own Id: OTP-18958 Aux Id: GH-8120, PR-8275

      Debugger 5.3.1.2

      Fixed Bugs and Malfunctions

      • The maybe expression is now supported in the Debugger.

        Own Id: OTP-18740 Aux Id: GH-7410, PR-7599

      Debugger 5.3.1.1

      Fixed Bugs and Malfunctions

      • The call int:no_break(Module) did not remove any breakpoints.

        Own Id: OTP-18644 Aux Id: GH-7336

      Debugger 5.3.1

      Fixed Bugs and Malfunctions

      • Fixed a bug that would cause analysis to crash.

        Own Id: OTP-18372 Aux Id: GH-6580

      Debugger 5.3

      Improvements and New Features

      • The configuration files .erlang, .erlang.cookie and .erlang.crypt can now be located in the XDG /usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1407)) --- old//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger_chapter.html 2026-08-21 04:00:20.195299787 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/debugger_chapter.html 2026-08-21 04:00:20.195299787 +0000 @@ -110,12 +110,12 @@ window, View Module window, or Attach Process window.

        Executable Lines

        To have an effect, a breakpoint must be set at an executable line, which is a line of code containing an executable expression such as a matching or a function call. A blank line or a line containing a comment, function head, or -pattern in a case statement or receive statement is not executable.

        In the following example, lines 2, 4, 6, 8, and 11 are executable lines:

        1: is_loaded(Module,Compiled) ->
        -2:   case get_file(Module,Compiled) of
        -3:     {ok,File} ->
        -4:       case code:which(Module) of
        +pattern in a case statement or receive statement is not executable.

        In the following example, lines 2, 4, 6, 8, and 11 are executable lines:

        1: is_loaded(Module,Compiled) ->
        +2:   case get_file(Module,Compiled) of
        +3:     {ok,File} ->
        +4:       case code:which(Module) of
         5:         ?TAG ->
        -6:           {loaded,File};
        +6:           {loaded,File};
         7:         _ ->
         8:           unloaded
         9:       end;
        @@ -136,13 +136,13 @@
         returns unbound or {value,Value}.

        Conditional Break Dialog Window

        Right-click the Module entry to open a popup menu from which the appropriate module can be selected.

        Example:

        A conditional breakpoint calling c_test:c_break/1 is added at line 6 in module fact. Each time the breakpoint is reached, the function is called. When N is -equal to 3, the function returns true and the process stops.

        Extract from fact.erl:

        5. fac(0) -> 1;
        -6. fac(N) when N > 0, is_integer(N) -> N * fac(N-1).

        Definition of c_test:c_break/1:

        -module(c_test).
        --export([c_break/1]).
        +equal to 3, the function returns true and the process stops.

        Extract from fact.erl:

        5. fac(0) -> 1;
        +6. fac(N) when N > 0, is_integer(N) -> N * fac(N-1).

        Definition of c_test:c_break/1:

        -module(c_test).
        +-export([c_break/1]).
         
        -c_break(Bindings) ->
        -    case int:get_binding('N', Bindings) of
        -        {value, 3} ->
        +c_break(Bindings) ->
        +    case int:get_binding('N', Bindings) of
        +        {value, 3} ->
                     true;
                 _ ->
                     false
        @@ -151,12 +151,12 @@
         right-click the Module entry.

        To bring up all functions of the module in the listbox, click the OK button (or press the Return or Tab key) when a module name has been specified,.

        Stack Trace

        The Erlang emulator keeps track of a stack trace, information about recent function calls. This information is used if an error occurs, for example:

        1> catch a+1.
        -{'EXIT',{badarith,[{erlang,'+',[a,1],[]},
        -                   {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,573}]},
        -                   {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,357}]},
        -                   {shell,exprs,7,[{file,"shell.erl"},{line,674}]},
        -                   {shell,eval_exprs,7,[{file,"shell.erl"},{line,629}]},
        -                   {shell,eval_loop,3,[{file,"shell.erl"},{line,614}]}]}}

        For details about the stack trace, see section +{'EXIT',{badarith,[{erlang,'+',[a,1],[]}, + {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,573}]}, + {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,357}]}, + {shell,exprs,7,[{file,"shell.erl"},{line,674}]}, + {shell,eval_exprs,7,[{file,"shell.erl"},{line,629}]}, + {shell,eval_loop,3,[{file,"shell.erl"},{line,614}]}]}}

        For details about the stack trace, see section Errors and Error Handling in the Erlang Reference Manual.

        Debugger emulates the stack trace by keeping track of recently called interpreted functions. (The real stack trace cannot be used, as it shows which /usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/i.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/i.html 2026-08-21 04:00:20.218299936 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/i.html 2026-08-21 04:00:20.218299936 +0000 @@ -99,9 +99,9 @@ interpreted processes and break points.

        It is possible to attach to interpreted processes by only giving the corresponding process identity. By default, an attachment window is displayed. Processes at other Erlang nodes can be attached manually or automatically.

        The functions in this module are defined in the Erlang shell. That is, -they can be called without the i: prefix. For example:

        1> ii(t).
        -{module,t}
        -2> iaa([init]).
        +they can be called without the i: prefix. For example:

        1> ii(t).
        +{module,t}
        +2> iaa([init]).
         true
    /usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/int.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (962)) --- old//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/int.html 2026-08-21 04:00:20.245300112 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/int.html 2026-08-21 04:00:20.245300112 +0000 @@ -645,7 +645,7 @@

    Sets when and how to attach automatically to a process executing code in interpreted modules.

    By default when the interpreter is started, automatic attach is disabled.

    If Flags is an empty list, automatic attach is disabled.

    Otherwise Flags should be a list containing at least one of the following flags:

    • init - Attach when a process for the first time calls an interpreted -function.
    • break - Attach whenever a process reaches a breakpoint.
    • exit - Attach when a process terminates.

    When the specified event occurs, the function Function is called as:

    spawn(Module, Name, [Pid | Args])

    Pid is the pid of the process executing interpreted code.

    +function.
  • break - Attach whenever a process reaches a breakpoint.
  • exit - Attach when a process terminates.
  • When the specified event occurs, the function Function is called as:

    spawn(Module, Name, [Pid | Args])

    Pid is the pid of the process executing interpreted code.

    /usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (6709)) --- old//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/notes.html 2026-08-21 04:00:20.270300275 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/debugger-6.0.3/doc/html/notes.html 2026-08-21 04:00:20.271300281 +0000 @@ -89,24 +89,24 @@ -

    This document describes the changes made to the Debugger application.

    Debugger 6.0.3

    Fixed Bugs and Malfunctions

    • Fixed unbound error in interpreted modules

      Own Id: OTP-19719 Aux Id: GH-10057, PR-10066

    Debugger 6.0.2

    Fixed Bugs and Malfunctions

    • Fixed debugger priv dir, which was removed and caused crashes when the icons could not be found.

      Own Id: OTP-19687 Aux Id: PR-9994, GH-9858

    Debugger 6.0.1

    Fixed Bugs and Malfunctions

    • Restore deleted icon so that debugger does not crash on startup.

      Own Id: OTP-19641 Aux Id: GH-9858, PR-9861

    Debugger 6.0

    Fixed Bugs and Malfunctions

    • Error handling has been improved when modules fail to load.

      Own Id: OTP-19484 Aux Id: GH-7819, PR-9399

    Improvements and New Features

    • Comprehensions have been extended with zip generators according to EEP 73.

      Example:

      1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
      -[5,7,9]

      Own Id: OTP-19184 Aux Id: PR-8926

    • New strict generators have been added for comprehensions.

      The currently existing generators are "relaxed": they ignore terms in the +

      This document describes the changes made to the Debugger application.

      Debugger 6.0.3

      Fixed Bugs and Malfunctions

      • Fixed unbound error in interpreted modules

        Own Id: OTP-19719 Aux Id: GH-10057, PR-10066

      Debugger 6.0.2

      Fixed Bugs and Malfunctions

      • Fixed debugger priv dir, which was removed and caused crashes when the icons could not be found.

        Own Id: OTP-19687 Aux Id: PR-9994, GH-9858

      Debugger 6.0.1

      Fixed Bugs and Malfunctions

      • Restore deleted icon so that debugger does not crash on startup.

        Own Id: OTP-19641 Aux Id: GH-9858, PR-9861

      Debugger 6.0

      Fixed Bugs and Malfunctions

      • Error handling has been improved when modules fail to load.

        Own Id: OTP-19484 Aux Id: GH-7819, PR-9399

      Improvements and New Features

      • Comprehensions have been extended with zip generators according to EEP 73.

        Example:

        1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
        +[5,7,9]

        Own Id: OTP-19184 Aux Id: PR-8926

      • New strict generators have been added for comprehensions.

        The currently existing generators are "relaxed": they ignore terms in the right-hand side expression that do not match the left-hand side pattern.

        The new strict generators fail with exception badmatch if a pattern doesn't match.

        Examples:

        Using the current relaxed generator operator <-, any element not matching -the pattern {_,_} will be silently discarded:

        1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
        -[{ok,1},{error,2}]

        If the intention is that all lists processed by a list comprehension must only +the pattern {_,_} will be silently discarded:

        1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
        +[{ok,1},{error,2}]

        If the intention is that all lists processed by a list comprehension must only contain tuples of size two, using the new strict version of the operator ensures -that term not matching will cause a crash:

        2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
        +that term not matching will cause a crash:

        2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
         ** exception error: no match of right hand side value ok

        Using the strict generator operator to mark the intention that all list elements must match the pattern could help finding mistakes quicker if something unpexected is added to the list processed by the generator.

        The strict version for bitstring generators is <:=.

        Own Id: OTP-19317 Aux Id: PR-8625

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      Debugger 5.5.0.1

      Fixed Bugs and Malfunctions

      • Fix unbound error in interpreted modules

        Own Id: OTP-19719 Aux Id: GH-10057, PR-10066

      Debugger 5.5

      Fixed Bugs and Malfunctions

      • Defining a fun in the shell using the syntax fun Name/Arity would fail. This has been corrected so that the following now works:

        1> F = fun is_atom/1.
         #Fun.erl.42.18682967>
        -> F(a).
        +> F(a).
         true
         3> Id = fun id/1.
         #Fun.erl.42.18682967>
        -4> Id(42).
        +4> Id(42).
         ** exception error: undefined shell command id/1
        -5> id(I) -> I.
        +5> id(I) -> I.
         ok
        -6> Id(42).
        +6> Id(42).
         42

        The Debugger has also been corrected to correctly handle this syntax for a BIF.

        Own Id: OTP-19322 Aux Id: GH-8963, PR-8987

      Improvements and New Features

      • Erlang/OTP type specifications has been updated to eliminate overlapping domains.

        Own Id: OTP-19310 Aux Id: GH-8810, GH-8821, PR-8986

      Debugger 5.4

      Fixed Bugs and Malfunctions

      • The dependencies for this application are now listed in the app file.

        Own Id: OTP-18831 Aux Id: PR-7441

      Improvements and New Features

      • Type specs have been added to all API functions.

        Own Id: OTP-18819 Aux Id: PR-7781

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      • The Debugger now use a trace session for its internal use of tracing to avoid interfering with the user's use of tracing.

        Own Id: OTP-19074 Aux Id: PR-8389

      Debugger 5.3.4

      Fixed Bugs and Malfunctions

      • Guards with nested record expression could wrongly evaluate to false.

        Own Id: OTP-18958 Aux Id: GH-8120, PR-8275

      Debugger 5.3.3

      Fixed Bugs and Malfunctions

      • Map comprehensions now work in the Debugger.

        Own Id: OTP-18888 Aux Id: GH-7914

      Debugger 5.3.2

      Fixed Bugs and Malfunctions

      • The call int:no_break(Module) did not remove any breakpoints.

        Own Id: OTP-18644 Aux Id: GH-7336

      • The maybe expression is now supported in the Debugger.

        Own Id: OTP-18740 Aux Id: GH-7410, PR-7599

      Debugger 5.3.1.3

      Fixed Bugs and Malfunctions

      • Guards with nested record expression could wrongly evaluate to false.

        Own Id: OTP-18958 Aux Id: GH-8120, PR-8275

      Debugger 5.3.1.2

      Fixed Bugs and Malfunctions

      • The maybe expression is now supported in the Debugger.

        Own Id: OTP-18740 Aux Id: GH-7410, PR-7599

      Debugger 5.3.1.1

      Fixed Bugs and Malfunctions

      • The call int:no_break(Module) did not remove any breakpoints.

        Own Id: OTP-18644 Aux Id: GH-7336

      Debugger 5.3.1

      Fixed Bugs and Malfunctions

      • Fixed a bug that would cause analysis to crash.

        Own Id: OTP-18372 Aux Id: GH-6580

      Debugger 5.3

      Improvements and New Features

      • The configuration files .erlang, .erlang.cookie and .erlang.crypt can now be located in the XDG /usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> dialyzer - 5.4.0.1 - urn:uuid:6ceb5438-fba9-e9f8-cf1b-9b88269cd3ac + urn:uuid:0f6fe62b-34b2-7067-0d7d-0a69a7a33f44 en - 2026-08-21T03:49:57Z + 2042-09-22T17:08:58Z /usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub/OEBPS/dialyzer_chapter.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1095)) --- old//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub/OEBPS/dialyzer_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub/OEBPS/dialyzer_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -59,29 +59,29 @@ deduce). One implication of this is that if the user gives a spec for a function which overlaps with Dialyzer's inferred type, but is more restrictive, Dialyzer will trust those restrictions. This may then generate an error elsewhere that -follows from the erroneously restricted spec.

        Examples:

        Non-overlapping argument:

        -spec foo(boolean()) -> string().
        +follows from the erroneously restricted spec.

        Examples:

        Non-overlapping argument:

        -spec foo(boolean()) -> string().
         %% Dialyzer will infer: foo(integer()) -> string().
        -foo(N) ->
        -    integer_to_list(N).

        Since the type of the argument in the spec is different from the type that +foo(N) -> + integer_to_list(N).

        Since the type of the argument in the spec is different from the type that Dialyzer inferred, Dialyzer will generate the following warning:

        some_module.erl:7:2: Invalid type specification for function some_module:foo/1.
          The success typing is some_module:foo
        -          (integer()) -> string()
        +          (integer()) -> string()
          But the spec is some_module:foo
        -          (boolean()) -> string()
        - They do not overlap in the 1st argument

        Non-overlapping return:

        -spec bar(a | b) -> atom().
        +          (boolean()) -> string()
        + They do not overlap in the 1st argument

        Non-overlapping return:

        -spec bar(a | b) -> atom().
         %% Dialyzer will infer: bar(a | b) -> binary().
        -bar(a) -> <<"a">>;
        -bar(b) -> <<"b">>.

        Since the return value in the spec and the return value inferred by Dialyzer are +bar(a) -> <<"a">>; +bar(b) -> <<"b">>.

    Since the return value in the spec and the return value inferred by Dialyzer are different, Dialyzer will generate the following warning:

    some_module.erl:11:2: Invalid type specification for function some_module:bar/1.
      The success typing is some_module:bar
    -          ('a' | 'b') -> <<_:8>>
    +          ('a' | 'b') -> <<_:8>>
      But the spec is some_module:bar
    -          ('a' | 'b') -> atom()
    - The return types do not overlap

    Overlapping spec and inferred type:

    -spec baz(a | b) -> non_neg_integer().
    +          ('a' | 'b') -> atom()
    + The return types do not overlap

    Overlapping spec and inferred type:

    -spec baz(a | b) -> non_neg_integer().
     %% Dialyzer will infer: baz(b | c | d) -> -1 | 0 | 1.
    -baz(b) -> -1;
    -baz(c) -> 0;
    -baz(d) -> 1.

    Dialyzer will "trust" the spec and using the intersection of the spec and +baz(b) -> -1; +baz(c) -> 0; +baz(d) -> 1.

    Dialyzer will "trust" the spec and using the intersection of the spec and inferred type:

    baz(b) -> 0 | 1.

    Notice how the c and d from the argument to baz/1 and the -1 in the return from the inferred type were dropped once the spec and inferred type were intersected. This could result in warnings being emitted for later functions.

    For example, if baz/1 is called like this:

    call_baz1(A) ->
    /usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub/OEBPS/dialyzer.xhtml differs (HTML document, ASCII text, with very long lines (2451))
    --- old//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub/OEBPS/dialyzer.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub/OEBPS/dialyzer.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -146,21 +146,21 @@
     repeating options which would otherwise need to be given explicitly to Dialyzer
     on every invocation.

    The location of the configuration file can be set via the DIALYZER_CONFIG environment variable, and defaults to within the user_config from -filename:basedir/3.

    An example configuration file's contents might be:

          {incremental,
    -        {default_apps,[stdlib,kernel,erts]},
    -        {default_warning_apps,[stdlib]}
    -      }.
    -      {warnings, [no_improper_lists]}.
    -      {add_pathsa,["/users/samwise/potatoes/ebin"]}.
    -      {add_pathsz,["/users/smeagol/fish/ebin"]}.

    Requesting or Suppressing Warnings in Source Files

    Attribute -dialyzer() can be used for turning off warnings in a module by +filename:basedir/3.

    An example configuration file's contents might be:

          {incremental,
    +        {default_apps,[stdlib,kernel,erts]},
    +        {default_warning_apps,[stdlib]}
    +      }.
    +      {warnings, [no_improper_lists]}.
    +      {add_pathsa,["/users/samwise/potatoes/ebin"]}.
    +      {add_pathsz,["/users/smeagol/fish/ebin"]}.

    Requesting or Suppressing Warnings in Source Files

    Attribute -dialyzer() can be used for turning off warnings in a module by specifying functions or warning options. For example, to turn off all warnings -for the function f/0, include the following line:

    -dialyzer({nowarn_function, f/0}).

    To turn off warnings for improper lists, add the following line to the source +for the function f/0, include the following line:

    -dialyzer({nowarn_function, f/0}).

    To turn off warnings for improper lists, add the following line to the source file:

    -dialyzer(no_improper_lists).

    Attribute -dialyzer() is allowed after function declarations. Lists of warning -options or functions are allowed:

    -dialyzer([{nowarn_function, [f/0]}, no_improper_lists]).

    Warning options can be restricted to functions:

    -dialyzer({no_improper_lists, g/0}).
    -dialyzer({[no_return, no_match], [g/0, h/0]}).

    The warning option for underspecified functions, -Wunderspecs, can result in +options or functions are allowed:

    -dialyzer([{nowarn_function, [f/0]}, no_improper_lists]).

    Warning options can be restricted to functions:

    -dialyzer({no_improper_lists, g/0}).
    -dialyzer({[no_return, no_match], [g/0, h/0]}).

    The warning option for underspecified functions, -Wunderspecs, can result in useful warnings, but often functions with specifications that are strictly more allowing than the success typing cannot easily be modified to be less allowing. To turn off the warning for underspecified function f/0, include the following -line:

    -dialyzer({no_underspecs, f/0}).

    For help on the warning options, use dialyzer -Whelp. The options are also +line:

    -dialyzer({no_underspecs, f/0}).

    For help on the warning options, use dialyzer -Whelp. The options are also enumerated, see type warn_option/0.

    Attribute -dialyzer() can also be used for turning on warnings. For example, if a module has been fixed regarding unmatched returns, adding the following line can help in assuring that no new unmatched return warnings are introduced:

    -dialyzer(unmatched_returns).
    /usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub/OEBPS/notes.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (5167)) --- old//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -17,9 +17,9 @@

    Dialyzer Release Notes

    -

    This document describes the changes made to the Dialyzer application.

    Dialyzer 5.4.0.1

    Fixed Bugs and Malfunctions

    • Fix Dialyzer crash with overriding built-in types

      Own Id: OTP-19631 Aux Id: GH-11093, PR-11096

    Dialyzer 5.4

    Fixed Bugs and Malfunctions

    • The -Wno_unknown option will now prevent a warning being printed to standard output when the command line interface is used.

      Own Id: OTP-19262 Aux Id: GH-8822, PR-8885

    Improvements and New Features

    • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

      All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

      -type meter() :: integer().
      --type foot() :: integer().

      Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

      -nominal meter() :: integer().
      --nominal foot() :: integer().

      More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

      Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

      Own Id: OTP-19364 Aux Id: PR-9079

    • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

      Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

    • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

      Own Id: OTP-19575 Aux Id: PR-9670

    Dialyzer 5.3.1

    Fixed Bugs and Malfunctions

    • Fixed a crash caused by the use of opaque types.

      Own Id: OTP-19439 Aux Id: ERIERL-1183, PR-9314

    Dialyzer 5.3

    Fixed Bugs and Malfunctions

    • Fixed type inference for erlang:system_info(logical_processors).

      Own Id: OTP-19307 Aux Id: PR-8954, GH-8948

    • Dialyzer would crash when attempting to analyze a module compiled with the line_coverage option.

      Own Id: OTP-19344 Aux Id: GH-9027, PR-9034

    Improvements and New Features

    • Erlang/OTP type specifications has been updated to eliminate overlapping domains.

      Own Id: OTP-19310 Aux Id: GH-8810, GH-8821, PR-8986

    Dialyzer 5.2.1

    Fixed Bugs and Malfunctions

    • Man pages are now available for erl, erlc, dialyzer, and all other programs that are included in Erlang/OTP.

      Own Id: OTP-19201 Aux Id: PR-8740

    Dialyzer 5.2

    Improvements and New Features

    • The --gui option for Dialyzer has been removed.

      Own Id: OTP-18667 Aux Id: PR-7443

    • The documentation has been migrated to use Markdown and ExDoc.

      Own Id: OTP-18955 Aux Id: PR-8026

    Dialyzer 5.1.3.1

    Fixed Bugs and Malfunctions

    • Fixed a crash caused by the use of opaque types.

      Own Id: OTP-19439 Aux Id: ERIERL-1183, PR-9314

    Dialyzer 5.1.3

    Fixed Bugs and Malfunctions

    • Fixed an issue with bitstring type inference on segments following UTF-8/16/32 segments.

      Own Id: OTP-19068 Aux Id: GH-8383

    Dialyzer 5.1.2

    Fixed Bugs and Malfunctions

    • Fix dialyzer --output flag to work. This option was accidentally removed in +

      This document describes the changes made to the Dialyzer application.

      Dialyzer 5.4.0.1

      Fixed Bugs and Malfunctions

      • Fix Dialyzer crash with overriding built-in types

        Own Id: OTP-19631 Aux Id: GH-11093, PR-11096

      Dialyzer 5.4

      Fixed Bugs and Malfunctions

      • The -Wno_unknown option will now prevent a warning being printed to standard output when the command line interface is used.

        Own Id: OTP-19262 Aux Id: GH-8822, PR-8885

      Improvements and New Features

      • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

        All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

        -type meter() :: integer().
        +-type foot() :: integer().

        Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

        -nominal meter() :: integer().
        +-nominal foot() :: integer().

        More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

        Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

        Own Id: OTP-19364 Aux Id: PR-9079

      • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

        Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      Dialyzer 5.3.1

      Fixed Bugs and Malfunctions

      • Fixed a crash caused by the use of opaque types.

        Own Id: OTP-19439 Aux Id: ERIERL-1183, PR-9314

      Dialyzer 5.3

      Fixed Bugs and Malfunctions

      • Fixed type inference for erlang:system_info(logical_processors).

        Own Id: OTP-19307 Aux Id: PR-8954, GH-8948

      • Dialyzer would crash when attempting to analyze a module compiled with the line_coverage option.

        Own Id: OTP-19344 Aux Id: GH-9027, PR-9034

      Improvements and New Features

      • Erlang/OTP type specifications has been updated to eliminate overlapping domains.

        Own Id: OTP-19310 Aux Id: GH-8810, GH-8821, PR-8986

      Dialyzer 5.2.1

      Fixed Bugs and Malfunctions

      • Man pages are now available for erl, erlc, dialyzer, and all other programs that are included in Erlang/OTP.

        Own Id: OTP-19201 Aux Id: PR-8740

      Dialyzer 5.2

      Improvements and New Features

      • The --gui option for Dialyzer has been removed.

        Own Id: OTP-18667 Aux Id: PR-7443

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      Dialyzer 5.1.3.1

      Fixed Bugs and Malfunctions

      • Fixed a crash caused by the use of opaque types.

        Own Id: OTP-19439 Aux Id: ERIERL-1183, PR-9314

      Dialyzer 5.1.3

      Fixed Bugs and Malfunctions

      • Fixed an issue with bitstring type inference on segments following UTF-8/16/32 segments.

        Own Id: OTP-19068 Aux Id: GH-8383

      Dialyzer 5.1.2

      Fixed Bugs and Malfunctions

      • Fix dialyzer --output flag to work. This option was accidentally removed in OTP 26.0.

        Own Id: OTP-18767 Aux Id: PR-7657

      • Fixed a crash in contract checking relating to opaque types.

        Own Id: OTP-18772 Aux Id: GH-7676

      Dialyzer 5.1.1

      Fixed Bugs and Malfunctions

      • Fixed a bug that caused dialyzer to crash when analyzing bogus code that contained the literal atom undefined in segment sizes.

        Own Id: OTP-18629 Aux Id: GH-7325

      • Dialyzer could crash when attempting to analyze a module that defined a type called product/.

        Own Id: OTP-18738 Aux Id: GH-7584

      Dialyzer 5.1

      Fixed Bugs and Malfunctions

      • When checking behaviors, Dialyzer could generate false warning that a callback /usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2451)) --- old//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.html 2026-08-21 04:00:20.370300926 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer.html 2026-08-21 04:00:20.370300926 +0000 @@ -217,21 +217,21 @@ repeating options which would otherwise need to be given explicitly to Dialyzer on every invocation.

        The location of the configuration file can be set via the DIALYZER_CONFIG environment variable, and defaults to within the user_config from -filename:basedir/3.

        An example configuration file's contents might be:

              {incremental,
        -        {default_apps,[stdlib,kernel,erts]},
        -        {default_warning_apps,[stdlib]}
        -      }.
        -      {warnings, [no_improper_lists]}.
        -      {add_pathsa,["/users/samwise/potatoes/ebin"]}.
        -      {add_pathsz,["/users/smeagol/fish/ebin"]}.

        Requesting or Suppressing Warnings in Source Files

        Attribute -dialyzer() can be used for turning off warnings in a module by +filename:basedir/3.

        An example configuration file's contents might be:

              {incremental,
        +        {default_apps,[stdlib,kernel,erts]},
        +        {default_warning_apps,[stdlib]}
        +      }.
        +      {warnings, [no_improper_lists]}.
        +      {add_pathsa,["/users/samwise/potatoes/ebin"]}.
        +      {add_pathsz,["/users/smeagol/fish/ebin"]}.

        Requesting or Suppressing Warnings in Source Files

        Attribute -dialyzer() can be used for turning off warnings in a module by specifying functions or warning options. For example, to turn off all warnings -for the function f/0, include the following line:

        -dialyzer({nowarn_function, f/0}).

        To turn off warnings for improper lists, add the following line to the source +for the function f/0, include the following line:

        -dialyzer({nowarn_function, f/0}).

        To turn off warnings for improper lists, add the following line to the source file:

        -dialyzer(no_improper_lists).

        Attribute -dialyzer() is allowed after function declarations. Lists of warning -options or functions are allowed:

        -dialyzer([{nowarn_function, [f/0]}, no_improper_lists]).

        Warning options can be restricted to functions:

        -dialyzer({no_improper_lists, g/0}).
        -dialyzer({[no_return, no_match], [g/0, h/0]}).

        The warning option for underspecified functions, -Wunderspecs, can result in +options or functions are allowed:

        -dialyzer([{nowarn_function, [f/0]}, no_improper_lists]).

        Warning options can be restricted to functions:

        -dialyzer({no_improper_lists, g/0}).
        -dialyzer({[no_return, no_match], [g/0, h/0]}).

        The warning option for underspecified functions, -Wunderspecs, can result in useful warnings, but often functions with specifications that are strictly more allowing than the success typing cannot easily be modified to be less allowing. To turn off the warning for underspecified function f/0, include the following -line:

        -dialyzer({no_underspecs, f/0}).

        For help on the warning options, use dialyzer -Whelp. The options are also +line:

        -dialyzer({no_underspecs, f/0}).

        For help on the warning options, use dialyzer -Whelp. The options are also enumerated, see type warn_option/0.

        Attribute -dialyzer() can also be used for turning on warnings. For example, if a module has been fixed regarding unmatched returns, adding the following line can help in assuring that no new unmatched return warnings are introduced:

        -dialyzer(unmatched_returns).
        /usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1095)) --- old//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer_chapter.html 2026-08-21 04:00:20.390301056 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/dialyzer_chapter.html 2026-08-21 04:00:20.390301056 +0000 @@ -131,29 +131,29 @@ deduce). One implication of this is that if the user gives a spec for a function which overlaps with Dialyzer's inferred type, but is more restrictive, Dialyzer will trust those restrictions. This may then generate an error elsewhere that -follows from the erroneously restricted spec.

        Examples:

        Non-overlapping argument:

        -spec foo(boolean()) -> string().
        +follows from the erroneously restricted spec.

        Examples:

        Non-overlapping argument:

        -spec foo(boolean()) -> string().
         %% Dialyzer will infer: foo(integer()) -> string().
        -foo(N) ->
        -    integer_to_list(N).

        Since the type of the argument in the spec is different from the type that +foo(N) -> + integer_to_list(N).

        Since the type of the argument in the spec is different from the type that Dialyzer inferred, Dialyzer will generate the following warning:

        some_module.erl:7:2: Invalid type specification for function some_module:foo/1.
          The success typing is some_module:foo
        -          (integer()) -> string()
        +          (integer()) -> string()
          But the spec is some_module:foo
        -          (boolean()) -> string()
        - They do not overlap in the 1st argument

        Non-overlapping return:

        -spec bar(a | b) -> atom().
        +          (boolean()) -> string()
        + They do not overlap in the 1st argument

        Non-overlapping return:

        -spec bar(a | b) -> atom().
         %% Dialyzer will infer: bar(a | b) -> binary().
        -bar(a) -> <<"a">>;
        -bar(b) -> <<"b">>.

        Since the return value in the spec and the return value inferred by Dialyzer are +bar(a) -> <<"a">>; +bar(b) -> <<"b">>.

    Since the return value in the spec and the return value inferred by Dialyzer are different, Dialyzer will generate the following warning:

    some_module.erl:11:2: Invalid type specification for function some_module:bar/1.
      The success typing is some_module:bar
    -          ('a' | 'b') -> <<_:8>>
    +          ('a' | 'b') -> <<_:8>>
      But the spec is some_module:bar
    -          ('a' | 'b') -> atom()
    - The return types do not overlap

    Overlapping spec and inferred type:

    -spec baz(a | b) -> non_neg_integer().
    +          ('a' | 'b') -> atom()
    + The return types do not overlap

    Overlapping spec and inferred type:

    -spec baz(a | b) -> non_neg_integer().
     %% Dialyzer will infer: baz(b | c | d) -> -1 | 0 | 1.
    -baz(b) -> -1;
    -baz(c) -> 0;
    -baz(d) -> 1.

    Dialyzer will "trust" the spec and using the intersection of the spec and +baz(b) -> -1; +baz(c) -> 0; +baz(d) -> 1.

    Dialyzer will "trust" the spec and using the intersection of the spec and inferred type:

    baz(b) -> 0 | 1.

    Notice how the c and d from the argument to baz/1 and the -1 in the return from the inferred type were dropped once the spec and inferred type were intersected. This could result in warnings being emitted for later functions.

    For example, if baz/1 is called like this:

    call_baz1(A) ->
    /usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (7267))
    --- old//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/notes.html	2026-08-21 04:00:20.422301264 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/dialyzer-5.4.0.1/doc/html/notes.html	2026-08-21 04:00:20.422301264 +0000
    @@ -89,9 +89,9 @@
       
     
     
    -

    This document describes the changes made to the Dialyzer application.

    Dialyzer 5.4.0.1

    Fixed Bugs and Malfunctions

    • Fix Dialyzer crash with overriding built-in types

      Own Id: OTP-19631 Aux Id: GH-11093, PR-11096

    Dialyzer 5.4

    Fixed Bugs and Malfunctions

    • The -Wno_unknown option will now prevent a warning being printed to standard output when the command line interface is used.

      Own Id: OTP-19262 Aux Id: GH-8822, PR-8885

    Improvements and New Features

    • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

      All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

      -type meter() :: integer().
      --type foot() :: integer().

      Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

      -nominal meter() :: integer().
      --nominal foot() :: integer().

      More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

      Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

      Own Id: OTP-19364 Aux Id: PR-9079

    • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

      Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

    • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

      Own Id: OTP-19575 Aux Id: PR-9670

    Dialyzer 5.3.1

    Fixed Bugs and Malfunctions

    • Fixed a crash caused by the use of opaque types.

      Own Id: OTP-19439 Aux Id: ERIERL-1183, PR-9314

    Dialyzer 5.3

    Fixed Bugs and Malfunctions

    • Fixed type inference for erlang:system_info(logical_processors).

      Own Id: OTP-19307 Aux Id: PR-8954, GH-8948

    • Dialyzer would crash when attempting to analyze a module compiled with the line_coverage option.

      Own Id: OTP-19344 Aux Id: GH-9027, PR-9034

    Improvements and New Features

    • Erlang/OTP type specifications has been updated to eliminate overlapping domains.

      Own Id: OTP-19310 Aux Id: GH-8810, GH-8821, PR-8986

    Dialyzer 5.2.1

    Fixed Bugs and Malfunctions

    • Man pages are now available for erl, erlc, dialyzer, and all other programs that are included in Erlang/OTP.

      Own Id: OTP-19201 Aux Id: PR-8740

    Dialyzer 5.2

    Improvements and New Features

    • The --gui option for Dialyzer has been removed.

      Own Id: OTP-18667 Aux Id: PR-7443

    • The documentation has been migrated to use Markdown and ExDoc.

      Own Id: OTP-18955 Aux Id: PR-8026

    Dialyzer 5.1.3.1

    Fixed Bugs and Malfunctions

    • Fixed a crash caused by the use of opaque types.

      Own Id: OTP-19439 Aux Id: ERIERL-1183, PR-9314

    Dialyzer 5.1.3

    Fixed Bugs and Malfunctions

    • Fixed an issue with bitstring type inference on segments following UTF-8/16/32 segments.

      Own Id: OTP-19068 Aux Id: GH-8383

    Dialyzer 5.1.2

    Fixed Bugs and Malfunctions

    • Fix dialyzer --output flag to work. This option was accidentally removed in +

      This document describes the changes made to the Dialyzer application.

      Dialyzer 5.4.0.1

      Fixed Bugs and Malfunctions

      • Fix Dialyzer crash with overriding built-in types

        Own Id: OTP-19631 Aux Id: GH-11093, PR-11096

      Dialyzer 5.4

      Fixed Bugs and Malfunctions

      • The -Wno_unknown option will now prevent a warning being printed to standard output when the command line interface is used.

        Own Id: OTP-19262 Aux Id: GH-8822, PR-8885

      Improvements and New Features

      • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

        All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

        -type meter() :: integer().
        +-type foot() :: integer().

        Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

        -nominal meter() :: integer().
        +-nominal foot() :: integer().

        More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

        Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

        Own Id: OTP-19364 Aux Id: PR-9079

      • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

        Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      Dialyzer 5.3.1

      Fixed Bugs and Malfunctions

      • Fixed a crash caused by the use of opaque types.

        Own Id: OTP-19439 Aux Id: ERIERL-1183, PR-9314

      Dialyzer 5.3

      Fixed Bugs and Malfunctions

      • Fixed type inference for erlang:system_info(logical_processors).

        Own Id: OTP-19307 Aux Id: PR-8954, GH-8948

      • Dialyzer would crash when attempting to analyze a module compiled with the line_coverage option.

        Own Id: OTP-19344 Aux Id: GH-9027, PR-9034

      Improvements and New Features

      • Erlang/OTP type specifications has been updated to eliminate overlapping domains.

        Own Id: OTP-19310 Aux Id: GH-8810, GH-8821, PR-8986

      Dialyzer 5.2.1

      Fixed Bugs and Malfunctions

      • Man pages are now available for erl, erlc, dialyzer, and all other programs that are included in Erlang/OTP.

        Own Id: OTP-19201 Aux Id: PR-8740

      Dialyzer 5.2

      Improvements and New Features

      • The --gui option for Dialyzer has been removed.

        Own Id: OTP-18667 Aux Id: PR-7443

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      Dialyzer 5.1.3.1

      Fixed Bugs and Malfunctions

      • Fixed a crash caused by the use of opaque types.

        Own Id: OTP-19439 Aux Id: ERIERL-1183, PR-9314

      Dialyzer 5.1.3

      Fixed Bugs and Malfunctions

      • Fixed an issue with bitstring type inference on segments following UTF-8/16/32 segments.

        Own Id: OTP-19068 Aux Id: GH-8383

      Dialyzer 5.1.2

      Fixed Bugs and Malfunctions

      • Fix dialyzer --output flag to work. This option was accidentally removed in OTP 26.0.

        Own Id: OTP-18767 Aux Id: PR-7657

      • Fixed a crash in contract checking relating to opaque types.

        Own Id: OTP-18772 Aux Id: GH-7676

      Dialyzer 5.1.1

      Fixed Bugs and Malfunctions

      • Fixed a bug that caused dialyzer to crash when analyzing bogus code that contained the literal atom undefined in segment sizes.

        Own Id: OTP-18629 Aux Id: GH-7325

      • Dialyzer could crash when attempting to analyze a module that defined a type called product/.

        Own Id: OTP-18738 Aux Id: GH-7584

      Dialyzer 5.1

      Fixed Bugs and Malfunctions

      • When checking behaviors, Dialyzer could generate false warning that a callback /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> diameter - 2.6.1.2 - urn:uuid:7090b740-0895-b18c-b9fc-b038fffa5f14 + urn:uuid:d998f7aa-6348-634f-5751-7611f27f9847 en - 2026-08-21T03:49:45Z + 2042-09-22T17:08:45Z /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameter_app.xhtml differs (HTML document, ASCII text, with very long lines (944)) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameter_app.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameter_app.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -597,12 +597,12 @@ diameter:start_service/2) is determined by the Application Identifier in the header of the incoming request message, the selected module being the one whose corresponding dictionary declares itself as defining either the application in -question or the Relay application.

        The argument packet() has the following signature.

        #diameter_packet{header = #diameter_header{},
        -                 avps   = [#diameter_avp{}],
        -                 msg    = record() | undefined,
        -                 errors = [Unsigned32() | {Unsigned32(), #diameter_avp{}}],
        -                 bin    = binary(),
        -                 transport_data = term()}

        The msg field will be undefined in case the request has been received in the +question or the Relay application.

        The argument packet() has the following signature.

        #diameter_packet{header = #diameter_header{},
        +                 avps   = [#diameter_avp{}],
        +                 msg    = record() | undefined,
        +                 errors = [Unsigned32() | {Unsigned32(), #diameter_avp{}}],
        +                 bin    = binary(),
        +                 transport_data = term()}

        The msg field will be undefined in case the request has been received in the relay application. Otherwise it contains the record representing the request as outlined in diameter_dict(4).

        The errors field specifies any results codes identifying errors found while decoding the request. This is used to set Result-Code and/or Failed-AVP in a /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameterc_cmd.xhtml differs (HTML document, ASCII text, with very long lines (591)) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameterc_cmd.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameterc_cmd.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -17,7 +17,7 @@

        diameterc

        -

        Compile a diameter dictionary to Erlang source.

        Synopsis

        diameterc [<options>] <file>

        Description

        The diameterc utility is used to compile a diameter +

        Compile a diameter dictionary to Erlang source.

        Synopsis

        diameterc [<options>] <file>

        Description

        The diameterc utility is used to compile a diameter dictionary file into Erlang source. The resulting source implements the interface diameter required to encode and decode the dictionary's messages and AVPs.

        The module diameter_make provides an alternate compilation interface.

        USAGE

        Compile a single dictionary file to Erlang /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameter_codec.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (613)) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameter_codec.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameter_codec.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -33,7 +33,7 @@ results may differ from those returned by the functions documented here, depending on configuration.

        The header() and packet() records below are defined in diameter.hrl, -which can be included as follows.

        -include_lib("diameter/include/diameter.hrl").

        Application-specific records are defined in the hrl files resulting from +which can be included as follows.

        -include_lib("diameter/include/diameter.hrl").

        Application-specific records are defined in the hrl files resulting from dictionary file compilation.

        DATA TYPES

        • uint8()  = 0..255

        • uint24() = 0..16777215

        • uint32() = 0..4294967295 - 8-bit, 24-bit and 32-bit integers occurring in Diameter and AVP headers.

        • avp() = #diameter_avp{} - The application-neutral representation of an AVP. Primarily intended for use by relay applications /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameter_dict.xhtml differs (HTML document, ASCII text, with very long lines (795)) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameter_dict.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameter_dict.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -208,14 +208,14 @@ an incoming request.

          In cases in which there is a choice between string() and binary() types for OctetString() and derived types, the representation is determined by the value of diameter:service_opt() -string_decode.

          Basic AVP Data Formats

          OctetString() = string() | binary()
          -Integer32()   = -2147483647..2147483647
          -Integer64()   = -9223372036854775807..9223372036854775807
          -Unsigned32()  = 0..4294967295
          -Unsigned64()  = 0..18446744073709551615
          -Float32()     = '-infinity' | float() | infinity
          -Float64()     = '-infinity' | float() | infinity
          -Grouped()     = record()

          On encode, an OctetString() can be specified as an iolist(), excessively large +string_decode.

          Basic AVP Data Formats

          OctetString() = string() | binary()
          +Integer32()   = -2147483647..2147483647
          +Integer64()   = -9223372036854775807..9223372036854775807
          +Unsigned32()  = 0..4294967295
          +Unsigned64()  = 0..18446744073709551615
          +Float32()     = '-infinity' | float() | infinity
          +Float64()     = '-infinity' | float() | infinity
          +Grouped()     = record()

          On encode, an OctetString() can be specified as an iolist(), excessively large floats (in absolute value) are equivalent to infinity or '-infinity' and excessively large integers result in encode failure. The records for grouped AVPs are as discussed in the previous section.

          Derived AVP Data Formats

          Address() = OctetString()
          @@ -223,14 +223,14 @@
           while an IPv6 address is parsed in any of the formats specified by section 2.2
           of RFC 2373, "Text Representation of Addresses". An IPv4 tuple() has length 4
           and contains values of type 0..255. An IPv6 tuple() has length 8 and contains
          -values of type 0..65535. The tuple representation is used on decode.

          Time() = {date(), time()}
          +values of type 0..65535. The tuple representation is used on decode.

          Time() = {date(), time()}
           
           where
           
          -  date() = {Year, Month, Day}
          -  time() = {Hour, Minute, Second}
          +  date() = {Year, Month, Day}
          +  time() = {Hour, Minute, Second}
           
          -  Year   = integer()
          +  Year   = integer()
             Month  = 1..12
             Day    = 1..31
             Hour   = 0..23
          @@ -258,8 +258,8 @@
           diameter respectively. The grammar of an OctetString-valued DiameterURI() is as
           specified in section 4.3 of RFC 6733. The record representation is used on
           decode.

          Enumerated() = Integer32()

          On encode, values can be specified using the macros defined in a dictionary's -hrl file.

          IPFilterRule()  = OctetString()
          -QoSFilterRule() = OctetString()

          Values of these types are not currently parsed by diameter.

          SEE ALSO

          diameterc(1), diameter, diameter_app, +hrl file.

          IPFilterRule()  = OctetString()
          +QoSFilterRule() = OctetString()

          Values of these types are not currently parsed by diameter.

          SEE ALSO

          diameterc(1), diameter, diameter_app, diameter_codec, diameter_make

          /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameter.xhtml differs (HTML document, ASCII text, with very long lines (1004)) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/diameter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -117,14 +117,14 @@ containing only 0 (NO_INBAND_SECURITY). If 1 (TLS) is specified then TLS is selected if the CER/CEA received from the peer offers it.

        • {'Acct-Application-Id', [Unsigned32()]}

        • {'Vendor-Specific-Application-Id', [Grouped()]}

        • {'Firmware-Revision',Unsigned32()}

        Note that each tuple communicates one or more AVP values. It is an error to specify duplicate tuples.

      • eval() = {M,F,A} | fun() | [eval() | A] - An expression that can be -evaluated as a function in the following sense.

        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) ->
        -    eval([F]).

        Applying an eval() E to an argument list A is meant +evaluated as a function in the following sense.

        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) ->
        +    eval([F]).

        Applying an eval() E to an argument list A is meant in the sense of eval([E|A]).

        Warning

        Beware of using fun expressions of the form fun Name/Arity in situations in which the fun is not short-lived and code is to be upgraded at runtime since any processes retaining such a fun will have a reference to old code. @@ -167,10 +167,10 @@ service_event() record. Can have one of the following types.

        • start

        • stop - The service is being started or stopped. No event precedes a start event. No event follows a stop event, and this event implies the -termination of all transport processes.

        • {up, Ref, Peer, Config, Pkt}

        • {up, Ref, Peer, Config}

        • {down, Ref, Peer, Config}

          Ref    = transport_ref()
          -Peer   = diameter_app:peer()
          -Config = {connect|listen, [transport_opt()]}
          -Pkt    = #diameter_packet{}

          The RFC 3539 watchdog state machine has transitioned into (up) or out of +termination of all transport processes.

        • {up, Ref, Peer, Config, Pkt}

        • {up, Ref, Peer, Config}

        • {down, Ref, Peer, Config}

          Ref    = transport_ref()
          +Peer   = diameter_app:peer()
          +Config = {connect|listen, [transport_opt()]}
          +Pkt    = #diameter_packet{}

          The RFC 3539 watchdog state machine has transitioned into (up) or out of (down) the OKAY state. If a #diameter_packet{} is present in an up event then there has been a capabilities exchange on a newly established transport connection and the record contains the received CER or CEA.

          Note that a single up or down event for a given peer corresponds to @@ -196,20 +196,20 @@ Pkt = #diameter_packet{}

    An incoming CER contained errors and has been answered with the indicated result code. Caps contains values for the local node only. Pkt contains the CER in question.

  • {'CER', timeout} - An expected CER was not received within -capx_timeout of connection establishment.

  • {'CEA', Result, Caps, Pkt}

    Result = ResultCode | atom() | {capabilities_cb, CB, ResultCode|discard}
    -Caps = #diameter_caps{}
    -Pkt  = #diameter_packet{}
    -ResultCode = integer()

    An incoming CEA has been rejected for the indicated reason. An +capx_timeout of connection establishment.

  • {'CEA', Result, Caps, Pkt}

    Result = ResultCode | atom() | {capabilities_cb, CB, ResultCode|discard}
    +Caps = #diameter_caps{}
    +Pkt  = #diameter_packet{}
    +ResultCode = integer()

    An incoming CEA has been rejected for the indicated reason. An integer-valued Result indicates the result code sent by the peer. Caps contains pairs of values for the local node and remote peer. Pkt contains the CEA in question. In the case of rejection by a capabilities callback, the tuple contains the rejecting callback.

  • {'CEA', Caps, Pkt}

    Caps = #diameter_caps{}
     Pkt  = #diameter_packet{}

    An incoming CEA contained errors and has been rejected. Caps contains only values for the local node. Pkt contains the CEA in question.

  • {'CEA', timeout} - An expected CEA was not received within -capx_timeout of connection establishment.

  • {watchdog, Ref, PeerRef, {From, To}, Config}

    Ref = transport_ref()
    -PeerRef = diameter_app:peer_ref()
    +capx_timeout of connection establishment.

  • {watchdog, Ref, PeerRef, {From, To}, Config}

    Ref = transport_ref()
    +PeerRef = diameter_app:peer_ref()
     From, To = initial | okay | suspect | down | reopen
    -Config = {connect|listen, [transport_opt()]}

    An RFC 3539 watchdog state machine has changed state.

  • any/0 - For forward compatibility, a subscriber should be prepared +Config = {connect|listen, [transport_opt()]}

    An RFC 3539 watchdog state machine has changed state.

  • any/0 - For forward compatibility, a subscriber should be prepared to receive info fields of forms other than the above.

  • service_name() = term() - Name of a service as passed to start_service/2 and with which the service is identified. There can be at most one service with a given name on a given node. Note that @@ -457,10 +457,10 @@ which a started transport process should be terminated if it has not yet established a connection. For example, the following options on a connecting transport request a connection with one peer over SCTP or another (typically -the same) over TCP.

    {transport_module, diameter_sctp}
    -{transport_config, SctpOpts, 5000}
    -{transport_module, diameter_tcp}
    -{transport_config, TcpOpts}

    To listen on both SCTP and TCP, define one transport for each.

  • {transport_module, atom()} - Module implementing +the same) over TCP.

    {transport_module, diameter_sctp}
    +{transport_config, SctpOpts, 5000}
    +{transport_module, diameter_tcp}
    +{transport_config, TcpOpts}

    To listen on both SCTP and TCP, define one transport for each.

  • {transport_module, atom()} - Module implementing a transport process as defined in diameter_transport. Defaults to diameter_tcp.

    Multiple transport_module and transport_config options are allowed. The @@ -2425,13 +2425,13 @@

    Remove previously added transports.

    Pred determines which transports to remove. An arity-3-valued Pred removes all transports for which Pred(Ref, Type, Opts) returns true, where Type and Opts are as passed to add_transport/2 and Ref is as returned by it. -The remaining forms are equivalent to an arity-3 fun as follows.

    Pred = fun(transport_ref(), list()):  fun(Ref, _, Opts) -> Pred(Ref, Opts) end
    -Pred = fun(list()):                   fun(_, _, Opts) -> Pred(Opts) end
    -Pred = transport_ref():               fun(Ref, _, _)  -> Pred == Ref end
    -Pred = list():                        fun(_, _, Opts) -> [] == Pred -- Opts end
    -Pred = true:                          fun(_, _, _) -> true end
    -Pred = false:                         fun(_, _, _) -> false end
    -Pred = {M,F,A}:  fun(Ref, Type, Opts) -> apply(M, F, [Ref, Type, Opts | A]) end

    Removing a transport causes the corresponding transport processes to be +The remaining forms are equivalent to an arity-3 fun as follows.

    Pred = fun(transport_ref(), list()):  fun(Ref, _, Opts) -> Pred(Ref, Opts) end
    +Pred = fun(list()):                   fun(_, _, Opts) -> Pred(Opts) end
    +Pred = transport_ref():               fun(Ref, _, _)  -> Pred == Ref end
    +Pred = list():                        fun(_, _, Opts) -> [] == Pred -- Opts end
    +Pred = true:                          fun(_, _, _) -> true end
    +Pred = false:                         fun(_, _, _) -> false end
    +Pred = {M,F,A}:  fun(Ref, Type, Opts) -> apply(M, F, [Ref, Type, Opts | A]) end

    Removing a transport causes the corresponding transport processes to be terminated. Whether or not a DPR message is sent to a peer is controlled by value of disconnect_cb configured on the transport.

    @@ -2475,52 +2475,52 @@ containing both configuration and information about established peer connections. An example return value with for a client service with Origin-Host "client.example.com" configured with a single transport connected -to "server.example.com" might look as follows.

    [[{ref,#Ref<0.0.0.93>},
    -  {type,connect},
    -  {options,[{transport_module,diameter_tcp},
    -            {transport_config,[{ip,{127,0,0,1}},
    -                               {raddr,{127,0,0,1}},
    -                               {rport,3868},
    -                               {reuseaddr,true}]}]},
    -  {watchdog,{<0.66.0>,-576460736368485571,okay}},
    -  {peer,{<0.67.0>,-576460736357885808}},
    -  {apps,[{0,common}]},
    -  {caps,[{origin_host,{"client.example.com","server.example.com"}},
    -         {origin_realm,{"example.com","example.com"}},
    -         {host_ip_address,{[{127,0,0,1}],[{127,0,0,1}]}},
    -         {vendor_id,{0,193}},
    -         {product_name,{"Client","Server"}},
    -         {origin_state_id,{[],[]}},
    -         {supported_vendor_id,{[],[]}},
    -         {auth_application_id,{[0],[0]}},
    -         {inband_security_id,{[],[0]}},
    -         {acct_application_id,{[],[]}},
    -         {vendor_specific_application_id,{[],[]}},
    -         {firmware_revision,{[],[]}},
    -         {avp,{[],[]}}]},
    -  {port,[{owner,<0.69.0>},
    -         {module,diameter_tcp},
    -         {socket,{{127,0,0,1},48758}},
    -         {peer,{{127,0,0,1},3868}},
    -         {statistics,[{recv_oct,656},
    -                      {recv_cnt,6},
    -                      {recv_max,148},
    -                      {recv_avg,109},
    -                      {recv_dvi,19},
    -                      {send_oct,836},
    -                      {send_cnt,6},
    -                      {send_max,184},
    -                      {send_avg,139},
    -                      {send_pend,0}]}]},
    -  {statistics,[{{{0,258,0},recv},3},
    -               {{{0,258,1},send},3},
    -               {{{0,258,0},recv,{'Result-Code',2001}},3},
    -               {{{0,257,0},recv},1},
    -               {{{0,257,1},send},1},
    -               {{{0,257,0},recv,{'Result-Code',2001}},1},
    -               {{{0,280,1},recv},2},
    -               {{{0,280,0},send},2},
    -               {{{0,280,0},send,{'Result-Code',2001}},2}]}]]

    Here ref is a transport_ref() and options +to "server.example.com" might look as follows.

    [[{ref,#Ref<0.0.0.93>},
    +  {type,connect},
    +  {options,[{transport_module,diameter_tcp},
    +            {transport_config,[{ip,{127,0,0,1}},
    +                               {raddr,{127,0,0,1}},
    +                               {rport,3868},
    +                               {reuseaddr,true}]}]},
    +  {watchdog,{<0.66.0>,-576460736368485571,okay}},
    +  {peer,{<0.67.0>,-576460736357885808}},
    +  {apps,[{0,common}]},
    +  {caps,[{origin_host,{"client.example.com","server.example.com"}},
    +         {origin_realm,{"example.com","example.com"}},
    +         {host_ip_address,{[{127,0,0,1}],[{127,0,0,1}]}},
    +         {vendor_id,{0,193}},
    +         {product_name,{"Client","Server"}},
    +         {origin_state_id,{[],[]}},
    +         {supported_vendor_id,{[],[]}},
    +         {auth_application_id,{[0],[0]}},
    +         {inband_security_id,{[],[0]}},
    +         {acct_application_id,{[],[]}},
    +         {vendor_specific_application_id,{[],[]}},
    +         {firmware_revision,{[],[]}},
    +         {avp,{[],[]}}]},
    +  {port,[{owner,<0.69.0>},
    +         {module,diameter_tcp},
    +         {socket,{{127,0,0,1},48758}},
    +         {peer,{{127,0,0,1},3868}},
    +         {statistics,[{recv_oct,656},
    +                      {recv_cnt,6},
    +                      {recv_max,148},
    +                      {recv_avg,109},
    +                      {recv_dvi,19},
    +                      {send_oct,836},
    +                      {send_cnt,6},
    +                      {send_max,184},
    +                      {send_avg,139},
    +                      {send_pend,0}]}]},
    +  {statistics,[{{{0,258,0},recv},3},
    +               {{{0,258,1},send},3},
    +               {{{0,258,0},recv,{'Result-Code',2001}},3},
    +               {{{0,257,0},recv},1},
    +               {{{0,257,1},send},1},
    +               {{{0,257,0},recv,{'Result-Code',2001}},1},
    +               {{{0,280,1},recv},2},
    +               {{{0,280,0},send},2},
    +               {{{0,280,0},send,{'Result-Code',2001}},2}]}]]

    Here ref is a transport_ref() and options /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/notes.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (6493)) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -17,9 +17,9 @@

    Release Notes

    -

    Releases are listed in reverse chronological order, most recent first.

    diameter 2.6.1.2

    Fixed Bugs and Malfunctions

    • Fix infinite loop in diameter_dist:route_session/2 when avp other than Session-Id has zero length.

      Own Id: OTP-20242 Aux Id: PR-11331

    • Fix crash in diameter_dist:route_session/2 when Session-Id (code: 263) avp has zero length.

      Own Id: OTP-20243 Aux Id: PR-11333

    diameter 2.6.1.1

    Fixed Bugs and Malfunctions

    • Fixed return value documentation of diameter:service_info(SvcName, statistics)

      Own Id: OTP-20150 Aux Id: GH-11105, PR-11146

    diameter 2.6.1

    Improvements and New Features

    • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

      A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

      make release_docs places the documentation in the released code under the doc folder.

      make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

      The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

      Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

      Improves the source Software-Bill-of-Materials

      • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
      • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
      • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

      Own Id: OTP-19886 Aux Id: PR-10434

    diameter 2.6

    Improvements and New Features

    • Add new option 'indirect_inherits' to diameter_make:codec/2

      Own Id: OTP-19626 Aux Id: GH-8235, PR-10149

    diameter 2.5.2

    Fixed Bugs and Malfunctions

    • Added documentation about 'proxy' and 'resend' options in diameter:handle_request/3

      Own Id: OTP-19768 Aux Id: GH-10150, PR-10182

    diameter 2.5.1

    Fixed Bugs and Malfunctions

    • With this change message_cb callback will be called with updated state for processing 'ack' after 'send'.

      Own Id: OTP-19753 Aux Id: PR-9815

    diameter 2.5

    Fixed Bugs and Malfunctions

    • With this change diameter will not crash when decoding a DiameterURI without port number.

      Own Id: OTP-19620 Aux Id: PR-9321

    Improvements and New Features

    • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

      All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

      -type meter() :: integer().
      --type foot() :: integer().

      Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

      -nominal meter() :: integer().
      --nominal foot() :: integer().

      More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

      Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

      Own Id: OTP-19364 Aux Id: PR-9079

    • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

      Own Id: OTP-19575 Aux Id: PR-9670

    • With this change diameter will not use slave terminology

      Own Id: OTP-19621 Aux Id: PR-9786

    diameter 2.4.1.1

    Fixed Bugs and Malfunctions

    • Added documentation about 'proxy' and 'resend' options in diameter:handle_request/3

      Own Id: OTP-19768 Aux Id: GH-10150, PR-10182

    diameter 2.4.1

    Fixed Bugs and Malfunctions

    • Function specs for the main API module has been updated.

      Own Id: OTP-19126 Aux Id: #8399

    • Man pages are now available for erl, erlc, dialyzer, and all other programs that are included in Erlang/OTP.

      Own Id: OTP-19201 Aux Id: PR-8740

    • diameter:stop_service/1 has been made more synchronous.

      Own Id: OTP-19206 Aux Id: ERIERL-1102

    diameter 2.4

    Improvements and New Features

    • -callback attributes have been added to diameter_app and diameter_transport.

      Own Id: OTP-18783 Aux Id: PR-7699

    • The documentation has been migrated to use Markdown and ExDoc.

      Own Id: OTP-18955 Aux Id: PR-8026

    • Pick peer can now also handle request of type #diameter_packet{}.

      Own Id: OTP-19090 Aux Id: PR-8399

    diameter 2.3.2.2

    Fixed Bugs and Malfunctions

    • Stop service has been made more synchronous.

      Own Id: OTP-19206 Aux Id: ERIERL-1102

    diameter 2.3.2.1

    Improvements and New Features

    • Pick peer can now also handle request of type #diameter_packet{}.

      Own Id: OTP-19090 Aux Id: PR-8399

    diameter 2.3.2

    Fixed Bugs and Malfunctions

    • Reduce the impact of calling service_info by not counting the binaries (on the heap) info, This is done by introducing an option, bins_info, which controls this.

      Own Id: OTP-19040 Aux Id: ERIERL-1060

    diameter 2.3.1

    Fixed Bugs and Malfunctions

    • Replaced unintentional Erlang Public License 1.1 headers in some files with +

      Releases are listed in reverse chronological order, most recent first.

      diameter 2.6.1.2

      Fixed Bugs and Malfunctions

      • Fix infinite loop in diameter_dist:route_session/2 when avp other than Session-Id has zero length.

        Own Id: OTP-20242 Aux Id: PR-11331

      • Fix crash in diameter_dist:route_session/2 when Session-Id (code: 263) avp has zero length.

        Own Id: OTP-20243 Aux Id: PR-11333

      diameter 2.6.1.1

      Fixed Bugs and Malfunctions

      • Fixed return value documentation of diameter:service_info(SvcName, statistics)

        Own Id: OTP-20150 Aux Id: GH-11105, PR-11146

      diameter 2.6.1

      Improvements and New Features

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      diameter 2.6

      Improvements and New Features

      • Add new option 'indirect_inherits' to diameter_make:codec/2

        Own Id: OTP-19626 Aux Id: GH-8235, PR-10149

      diameter 2.5.2

      Fixed Bugs and Malfunctions

      • Added documentation about 'proxy' and 'resend' options in diameter:handle_request/3

        Own Id: OTP-19768 Aux Id: GH-10150, PR-10182

      diameter 2.5.1

      Fixed Bugs and Malfunctions

      • With this change message_cb callback will be called with updated state for processing 'ack' after 'send'.

        Own Id: OTP-19753 Aux Id: PR-9815

      diameter 2.5

      Fixed Bugs and Malfunctions

      • With this change diameter will not crash when decoding a DiameterURI without port number.

        Own Id: OTP-19620 Aux Id: PR-9321

      Improvements and New Features

      • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

        All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

        -type meter() :: integer().
        +-type foot() :: integer().

        Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

        -nominal meter() :: integer().
        +-nominal foot() :: integer().

        More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

        Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

        Own Id: OTP-19364 Aux Id: PR-9079

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      • With this change diameter will not use slave terminology

        Own Id: OTP-19621 Aux Id: PR-9786

      diameter 2.4.1.1

      Fixed Bugs and Malfunctions

      • Added documentation about 'proxy' and 'resend' options in diameter:handle_request/3

        Own Id: OTP-19768 Aux Id: GH-10150, PR-10182

      diameter 2.4.1

      Fixed Bugs and Malfunctions

      • Function specs for the main API module has been updated.

        Own Id: OTP-19126 Aux Id: #8399

      • Man pages are now available for erl, erlc, dialyzer, and all other programs that are included in Erlang/OTP.

        Own Id: OTP-19201 Aux Id: PR-8740

      • diameter:stop_service/1 has been made more synchronous.

        Own Id: OTP-19206 Aux Id: ERIERL-1102

      diameter 2.4

      Improvements and New Features

      • -callback attributes have been added to diameter_app and diameter_transport.

        Own Id: OTP-18783 Aux Id: PR-7699

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      • Pick peer can now also handle request of type #diameter_packet{}.

        Own Id: OTP-19090 Aux Id: PR-8399

      diameter 2.3.2.2

      Fixed Bugs and Malfunctions

      • Stop service has been made more synchronous.

        Own Id: OTP-19206 Aux Id: ERIERL-1102

      diameter 2.3.2.1

      Improvements and New Features

      • Pick peer can now also handle request of type #diameter_packet{}.

        Own Id: OTP-19090 Aux Id: PR-8399

      diameter 2.3.2

      Fixed Bugs and Malfunctions

      • Reduce the impact of calling service_info by not counting the binaries (on the heap) info, This is done by introducing an option, bins_info, which controls this.

        Own Id: OTP-19040 Aux Id: ERIERL-1060

      diameter 2.3.1

      Fixed Bugs and Malfunctions

      • Replaced unintentional Erlang Public License 1.1 headers in some files with the intended Apache License 2.0 header.

        Own Id: OTP-18815 Aux Id: PR-7780

      diameter 2.3

      Improvements and New Features

      • Replace size/1 with either tuple_size/1 or byte_size/1

        The size/1 BIF is not optimized by the JIT, and its use can result in worse types for Dialyzer.

        When one knows that the value being tested must be a tuple, tuple_size/1 should always be preferred.

        When one knows that the value being tested must be a binary, /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1002)) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.html 2026-08-21 04:00:20.585302325 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter.html 2026-08-21 04:00:20.585302325 +0000 @@ -188,14 +188,14 @@ containing only 0 (NO_INBAND_SECURITY). If 1 (TLS) is specified then TLS is selected if the CER/CEA received from the peer offers it.

      • {'Acct-Application-Id', [Unsigned32()]}

      • {'Vendor-Specific-Application-Id', [Grouped()]}

      • {'Firmware-Revision',Unsigned32()}

      Note that each tuple communicates one or more AVP values. It is an error to specify duplicate tuples.

    • eval() = {M,F,A} | fun() | [eval() | A] - An expression that can be -evaluated as a function in the following sense.

      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) ->
      -    eval([F]).

      Applying an eval() E to an argument list A is meant +evaluated as a function in the following sense.

      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) ->
      +    eval([F]).

      Applying an eval() E to an argument list A is meant in the sense of eval([E|A]).

      Warning

      Beware of using fun expressions of the form fun Name/Arity in situations in which the fun is not short-lived and code is to be upgraded at runtime since any processes retaining such a fun will have a reference to old code. @@ -238,10 +238,10 @@ service_event() record. Can have one of the following types.

      • start

      • stop - The service is being started or stopped. No event precedes a start event. No event follows a stop event, and this event implies the -termination of all transport processes.

      • {up, Ref, Peer, Config, Pkt}

      • {up, Ref, Peer, Config}

      • {down, Ref, Peer, Config}

        Ref    = transport_ref()
        -Peer   = diameter_app:peer()
        -Config = {connect|listen, [transport_opt()]}
        -Pkt    = #diameter_packet{}

        The RFC 3539 watchdog state machine has transitioned into (up) or out of +termination of all transport processes.

      • {up, Ref, Peer, Config, Pkt}

      • {up, Ref, Peer, Config}

      • {down, Ref, Peer, Config}

        Ref    = transport_ref()
        +Peer   = diameter_app:peer()
        +Config = {connect|listen, [transport_opt()]}
        +Pkt    = #diameter_packet{}

        The RFC 3539 watchdog state machine has transitioned into (up) or out of (down) the OKAY state. If a #diameter_packet{} is present in an up event then there has been a capabilities exchange on a newly established transport connection and the record contains the received CER or CEA.

        Note that a single up or down event for a given peer corresponds to @@ -267,20 +267,20 @@ Pkt = #diameter_packet{}

        An incoming CER contained errors and has been answered with the indicated result code. Caps contains values for the local node only. Pkt contains the CER in question.

      • {'CER', timeout} - An expected CER was not received within -capx_timeout of connection establishment.

      • {'CEA', Result, Caps, Pkt}

        Result = ResultCode | atom() | {capabilities_cb, CB, ResultCode|discard}
        -Caps = #diameter_caps{}
        -Pkt  = #diameter_packet{}
        -ResultCode = integer()

        An incoming CEA has been rejected for the indicated reason. An +capx_timeout of connection establishment.

      • {'CEA', Result, Caps, Pkt}

        Result = ResultCode | atom() | {capabilities_cb, CB, ResultCode|discard}
        +Caps = #diameter_caps{}
        +Pkt  = #diameter_packet{}
        +ResultCode = integer()

        An incoming CEA has been rejected for the indicated reason. An integer-valued Result indicates the result code sent by the peer. Caps contains pairs of values for the local node and remote peer. Pkt contains the CEA in question. In the case of rejection by a capabilities callback, the tuple contains the rejecting callback.

      • {'CEA', Caps, Pkt}

        Caps = #diameter_caps{}
         Pkt  = #diameter_packet{}

        An incoming CEA contained errors and has been rejected. Caps contains only values for the local node. Pkt contains the CEA in question.

      • {'CEA', timeout} - An expected CEA was not received within -capx_timeout of connection establishment.

    • {watchdog, Ref, PeerRef, {From, To}, Config}

      Ref = transport_ref()
      -PeerRef = diameter_app:peer_ref()
      +capx_timeout of connection establishment.

  • {watchdog, Ref, PeerRef, {From, To}, Config}

    Ref = transport_ref()
    +PeerRef = diameter_app:peer_ref()
     From, To = initial | okay | suspect | down | reopen
    -Config = {connect|listen, [transport_opt()]}

    An RFC 3539 watchdog state machine has changed state.

  • any/0 - For forward compatibility, a subscriber should be prepared +Config = {connect|listen, [transport_opt()]}

    An RFC 3539 watchdog state machine has changed state.

  • any/0 - For forward compatibility, a subscriber should be prepared to receive info fields of forms other than the above.

  • service_name() = term() - Name of a service as passed to start_service/2 and with which the service is identified. There can be at most one service with a given name on a given node. Note that @@ -528,10 +528,10 @@ which a started transport process should be terminated if it has not yet established a connection. For example, the following options on a connecting transport request a connection with one peer over SCTP or another (typically -the same) over TCP.

    {transport_module, diameter_sctp}
    -{transport_config, SctpOpts, 5000}
    -{transport_module, diameter_tcp}
    -{transport_config, TcpOpts}

    To listen on both SCTP and TCP, define one transport for each.

  • {transport_module, atom()} - Module implementing +the same) over TCP.

    {transport_module, diameter_sctp}
    +{transport_config, SctpOpts, 5000}
    +{transport_module, diameter_tcp}
    +{transport_config, TcpOpts}

    To listen on both SCTP and TCP, define one transport for each.

  • {transport_module, atom()} - Module implementing a transport process as defined in diameter_transport. Defaults to diameter_tcp.

    Multiple transport_module and transport_config options are allowed. The @@ -2512,13 +2512,13 @@

    Remove previously added transports.

    Pred determines which transports to remove. An arity-3-valued Pred removes all transports for which Pred(Ref, Type, Opts) returns true, where Type and Opts are as passed to add_transport/2 and Ref is as returned by it. -The remaining forms are equivalent to an arity-3 fun as follows.

    Pred = fun(transport_ref(), list()):  fun(Ref, _, Opts) -> Pred(Ref, Opts) end
    -Pred = fun(list()):                   fun(_, _, Opts) -> Pred(Opts) end
    -Pred = transport_ref():               fun(Ref, _, _)  -> Pred == Ref end
    -Pred = list():                        fun(_, _, Opts) -> [] == Pred -- Opts end
    -Pred = true:                          fun(_, _, _) -> true end
    -Pred = false:                         fun(_, _, _) -> false end
    -Pred = {M,F,A}:  fun(Ref, Type, Opts) -> apply(M, F, [Ref, Type, Opts | A]) end

    Removing a transport causes the corresponding transport processes to be +The remaining forms are equivalent to an arity-3 fun as follows.

    Pred = fun(transport_ref(), list()):  fun(Ref, _, Opts) -> Pred(Ref, Opts) end
    +Pred = fun(list()):                   fun(_, _, Opts) -> Pred(Opts) end
    +Pred = transport_ref():               fun(Ref, _, _)  -> Pred == Ref end
    +Pred = list():                        fun(_, _, Opts) -> [] == Pred -- Opts end
    +Pred = true:                          fun(_, _, _) -> true end
    +Pred = false:                         fun(_, _, _) -> false end
    +Pred = {M,F,A}:  fun(Ref, Type, Opts) -> apply(M, F, [Ref, Type, Opts | A]) end

    Removing a transport causes the corresponding transport processes to be terminated. Whether or not a DPR message is sent to a peer is controlled by value of disconnect_cb configured on the transport.

    @@ -2562,52 +2562,52 @@ containing both configuration and information about established peer connections. An example return value with for a client service with Origin-Host "client.example.com" configured with a single transport connected -to "server.example.com" might look as follows.

    [[{ref,#Ref<0.0.0.93>},
    -  {type,connect},
    -  {options,[{transport_module,diameter_tcp},
    -            {transport_config,[{ip,{127,0,0,1}},
    -                               {raddr,{127,0,0,1}},
    -                               {rport,3868},
    -                               {reuseaddr,true}]}]},
    -  {watchdog,{<0.66.0>,-576460736368485571,okay}},
    -  {peer,{<0.67.0>,-576460736357885808}},
    -  {apps,[{0,common}]},
    -  {caps,[{origin_host,{"client.example.com","server.example.com"}},
    -         {origin_realm,{"example.com","example.com"}},
    -         {host_ip_address,{[{127,0,0,1}],[{127,0,0,1}]}},
    -         {vendor_id,{0,193}},
    -         {product_name,{"Client","Server"}},
    -         {origin_state_id,{[],[]}},
    -         {supported_vendor_id,{[],[]}},
    -         {auth_application_id,{[0],[0]}},
    -         {inband_security_id,{[],[0]}},
    -         {acct_application_id,{[],[]}},
    -         {vendor_specific_application_id,{[],[]}},
    -         {firmware_revision,{[],[]}},
    -         {avp,{[],[]}}]},
    -  {port,[{owner,<0.69.0>},
    -         {module,diameter_tcp},
    -         {socket,{{127,0,0,1},48758}},
    -         {peer,{{127,0,0,1},3868}},
    -         {statistics,[{recv_oct,656},
    -                      {recv_cnt,6},
    -                      {recv_max,148},
    -                      {recv_avg,109},
    -                      {recv_dvi,19},
    -                      {send_oct,836},
    -                      {send_cnt,6},
    -                      {send_max,184},
    -                      {send_avg,139},
    -                      {send_pend,0}]}]},
    -  {statistics,[{{{0,258,0},recv},3},
    -               {{{0,258,1},send},3},
    -               {{{0,258,0},recv,{'Result-Code',2001}},3},
    -               {{{0,257,0},recv},1},
    -               {{{0,257,1},send},1},
    -               {{{0,257,0},recv,{'Result-Code',2001}},1},
    -               {{{0,280,1},recv},2},
    -               {{{0,280,0},send},2},
    -               {{{0,280,0},send,{'Result-Code',2001}},2}]}]]

    Here ref is a transport_ref() and options +to "server.example.com" might look as follows.

    [[{ref,#Ref<0.0.0.93>},
    +  {type,connect},
    +  {options,[{transport_module,diameter_tcp},
    +            {transport_config,[{ip,{127,0,0,1}},
    +                               {raddr,{127,0,0,1}},
    +                               {rport,3868},
    +                               {reuseaddr,true}]}]},
    +  {watchdog,{<0.66.0>,-576460736368485571,okay}},
    +  {peer,{<0.67.0>,-576460736357885808}},
    +  {apps,[{0,common}]},
    +  {caps,[{origin_host,{"client.example.com","server.example.com"}},
    +         {origin_realm,{"example.com","example.com"}},
    +         {host_ip_address,{[{127,0,0,1}],[{127,0,0,1}]}},
    +         {vendor_id,{0,193}},
    +         {product_name,{"Client","Server"}},
    +         {origin_state_id,{[],[]}},
    +         {supported_vendor_id,{[],[]}},
    +         {auth_application_id,{[0],[0]}},
    +         {inband_security_id,{[],[0]}},
    +         {acct_application_id,{[],[]}},
    +         {vendor_specific_application_id,{[],[]}},
    +         {firmware_revision,{[],[]}},
    +         {avp,{[],[]}}]},
    +  {port,[{owner,<0.69.0>},
    +         {module,diameter_tcp},
    +         {socket,{{127,0,0,1},48758}},
    +         {peer,{{127,0,0,1},3868}},
    +         {statistics,[{recv_oct,656},
    +                      {recv_cnt,6},
    +                      {recv_max,148},
    +                      {recv_avg,109},
    +                      {recv_dvi,19},
    +                      {send_oct,836},
    +                      {send_cnt,6},
    +                      {send_max,184},
    +                      {send_avg,139},
    +                      {send_pend,0}]}]},
    +  {statistics,[{{{0,258,0},recv},3},
    +               {{{0,258,1},send},3},
    +               {{{0,258,0},recv,{'Result-Code',2001}},3},
    +               {{{0,257,0},recv},1},
    +               {{{0,257,1},send},1},
    +               {{{0,257,0},recv,{'Result-Code',2001}},1},
    +               {{{0,280,1},recv},2},
    +               {{{0,280,0},send},2},
    +               {{{0,280,0},send,{'Result-Code',2001}},2}]}]]

    Here ref is a transport_ref() and options /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_app.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (944)) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_app.html 2026-08-21 04:00:20.611302494 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_app.html 2026-08-21 04:00:20.611302494 +0000 @@ -684,12 +684,12 @@ diameter:start_service/2) is determined by the Application Identifier in the header of the incoming request message, the selected module being the one whose corresponding dictionary declares itself as defining either the application in -question or the Relay application.

    The argument packet() has the following signature.

    #diameter_packet{header = #diameter_header{},
    -                 avps   = [#diameter_avp{}],
    -                 msg    = record() | undefined,
    -                 errors = [Unsigned32() | {Unsigned32(), #diameter_avp{}}],
    -                 bin    = binary(),
    -                 transport_data = term()}

    The msg field will be undefined in case the request has been received in the +question or the Relay application.

    The argument packet() has the following signature.

    #diameter_packet{header = #diameter_header{},
    +                 avps   = [#diameter_avp{}],
    +                 msg    = record() | undefined,
    +                 errors = [Unsigned32() | {Unsigned32(), #diameter_avp{}}],
    +                 bin    = binary(),
    +                 transport_data = term()}

    The msg field will be undefined in case the request has been received in the relay application. Otherwise it contains the record representing the request as outlined in diameter_dict(4).

    The errors field specifies any results codes identifying errors found while decoding the request. This is used to set Result-Code and/or Failed-AVP in a /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_codec.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_codec.html 2026-08-21 04:00:20.633302638 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_codec.html 2026-08-21 04:00:20.633302638 +0000 @@ -104,7 +104,7 @@ results may differ from those returned by the functions documented here, depending on configuration.

    The header() and packet() records below are defined in diameter.hrl, -which can be included as follows.

    -include_lib("diameter/include/diameter.hrl").

    Application-specific records are defined in the hrl files resulting from +which can be included as follows.

    -include_lib("diameter/include/diameter.hrl").

    Application-specific records are defined in the hrl files resulting from dictionary file compilation.

    DATA TYPES

    • uint8()  = 0..255

    • uint24() = 0..16777215

    • uint32() = 0..4294967295 - 8-bit, 24-bit and 32-bit integers occurring in Diameter and AVP headers.

    • avp() = #diameter_avp{} - The application-neutral representation of an AVP. Primarily intended for use by relay applications /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_dict.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (800)) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_dict.html 2026-08-21 04:00:20.656302787 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameter_dict.html 2026-08-21 04:00:20.657302794 +0000 @@ -280,14 +280,14 @@ an incoming request.

      In cases in which there is a choice between string() and binary() types for OctetString() and derived types, the representation is determined by the value of diameter:service_opt() -string_decode.

      Basic AVP Data Formats

      OctetString() = string() | binary()
      -Integer32()   = -2147483647..2147483647
      -Integer64()   = -9223372036854775807..9223372036854775807
      -Unsigned32()  = 0..4294967295
      -Unsigned64()  = 0..18446744073709551615
      -Float32()     = '-infinity' | float() | infinity
      -Float64()     = '-infinity' | float() | infinity
      -Grouped()     = record()

      On encode, an OctetString() can be specified as an iolist(), excessively large +string_decode.

      Basic AVP Data Formats

      OctetString() = string() | binary()
      +Integer32()   = -2147483647..2147483647
      +Integer64()   = -9223372036854775807..9223372036854775807
      +Unsigned32()  = 0..4294967295
      +Unsigned64()  = 0..18446744073709551615
      +Float32()     = '-infinity' | float() | infinity
      +Float64()     = '-infinity' | float() | infinity
      +Grouped()     = record()

      On encode, an OctetString() can be specified as an iolist(), excessively large floats (in absolute value) are equivalent to infinity or '-infinity' and excessively large integers result in encode failure. The records for grouped AVPs are as discussed in the previous section.

      Derived AVP Data Formats

      Address() = OctetString()
      @@ -295,14 +295,14 @@
       while an IPv6 address is parsed in any of the formats specified by section 2.2
       of RFC 2373, "Text Representation of Addresses". An IPv4 tuple() has length 4
       and contains values of type 0..255. An IPv6 tuple() has length 8 and contains
      -values of type 0..65535. The tuple representation is used on decode.

      Time() = {date(), time()}
      +values of type 0..65535. The tuple representation is used on decode.

      Time() = {date(), time()}
       
       where
       
      -  date() = {Year, Month, Day}
      -  time() = {Hour, Minute, Second}
      +  date() = {Year, Month, Day}
      +  time() = {Hour, Minute, Second}
       
      -  Year   = integer()
      +  Year   = integer()
         Month  = 1..12
         Day    = 1..31
         Hour   = 0..23
      @@ -315,8 +315,8 @@
       UTF8String() can be specified as a binary, or as a nested list of binaries and
       codepoints.

      DiameterIdentity() = OctetString()

      A value must have length at least 1.

      DiameterURI() = OctetString()
                     | #href_anchor"" id="Enumerated">

      Enumerated() = Integer32()

      On encode, values can be specified using the macros defined in a dictionary's -hrl file.

      IPFilterRule()  = OctetString()
      -QoSFilterRule() = OctetString()

      Values of these types are not currently parsed by diameter.

      SEE ALSO

      diameterc(1), diameter, diameter_app, +hrl file.

      IPFilterRule()  = OctetString()
      +QoSFilterRule() = OctetString()

      Values of these types are not currently parsed by diameter.

      SEE ALSO

      diameterc(1), diameter, diameter_app, diameter_codec, diameter_make

      /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameterc_cmd.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (871)) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameterc_cmd.html 2026-08-21 04:00:20.673302898 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/diameterc_cmd.html 2026-08-21 04:00:20.673302898 +0000 @@ -89,7 +89,7 @@ -

      Compile a diameter dictionary to Erlang source.

      Synopsis

      diameterc [<options>] <file>

      Description

      The diameterc utility is used to compile a diameter +

      Compile a diameter dictionary to Erlang source.

      Synopsis

      diameterc [<options>] <file>

      Description

      The diameterc utility is used to compile a diameter dictionary file into Erlang source. The resulting source implements the interface diameter required to encode and decode the dictionary's messages and AVPs.

      The module diameter_make provides an alternate compilation interface.

      USAGE

      Compile a single dictionary file to Erlang /usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (8593)) --- old//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/notes.html 2026-08-21 04:00:20.700303074 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/diameter-2.6.1.2/doc/html/notes.html 2026-08-21 04:00:20.700303074 +0000 @@ -89,9 +89,9 @@ -

      Releases are listed in reverse chronological order, most recent first.

      diameter 2.6.1.2

      Fixed Bugs and Malfunctions

      • Fix infinite loop in diameter_dist:route_session/2 when avp other than Session-Id has zero length.

        Own Id: OTP-20242 Aux Id: PR-11331

      • Fix crash in diameter_dist:route_session/2 when Session-Id (code: 263) avp has zero length.

        Own Id: OTP-20243 Aux Id: PR-11333

      diameter 2.6.1.1

      Fixed Bugs and Malfunctions

      • Fixed return value documentation of diameter:service_info(SvcName, statistics)

        Own Id: OTP-20150 Aux Id: GH-11105, PR-11146

      diameter 2.6.1

      Improvements and New Features

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      diameter 2.6

      Improvements and New Features

      • Add new option 'indirect_inherits' to diameter_make:codec/2

        Own Id: OTP-19626 Aux Id: GH-8235, PR-10149

      diameter 2.5.2

      Fixed Bugs and Malfunctions

      • Added documentation about 'proxy' and 'resend' options in diameter:handle_request/3

        Own Id: OTP-19768 Aux Id: GH-10150, PR-10182

      diameter 2.5.1

      Fixed Bugs and Malfunctions

      • With this change message_cb callback will be called with updated state for processing 'ack' after 'send'.

        Own Id: OTP-19753 Aux Id: PR-9815

      diameter 2.5

      Fixed Bugs and Malfunctions

      • With this change diameter will not crash when decoding a DiameterURI without port number.

        Own Id: OTP-19620 Aux Id: PR-9321

      Improvements and New Features

      • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

        All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

        -type meter() :: integer().
        --type foot() :: integer().

        Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

        -nominal meter() :: integer().
        --nominal foot() :: integer().

        More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

        Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

        Own Id: OTP-19364 Aux Id: PR-9079

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      • With this change diameter will not use slave terminology

        Own Id: OTP-19621 Aux Id: PR-9786

      diameter 2.4.1.1

      Fixed Bugs and Malfunctions

      • Added documentation about 'proxy' and 'resend' options in diameter:handle_request/3

        Own Id: OTP-19768 Aux Id: GH-10150, PR-10182

      diameter 2.4.1

      Fixed Bugs and Malfunctions

      diameter 2.4

      Improvements and New Features

      • -callback attributes have been added to diameter_app and diameter_transport.

        Own Id: OTP-18783 Aux Id: PR-7699

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      • Pick peer can now also handle request of type #href_anchor"https://github.com/erlang/otp/pull/8399" title="">PR-8399

      diameter 2.3.2.2

      Fixed Bugs and Malfunctions

      • Stop service has been made more synchronous.

        Own Id: OTP-19206 Aux Id: ERIERL-1102

      diameter 2.3.2.1

      Improvements and New Features

      • Pick peer can now also handle request of type #diameter_packet{}.

        Own Id: OTP-19090 Aux Id: PR-8399

      diameter 2.3.2

      Fixed Bugs and Malfunctions

      • Reduce the impact of calling service_info by not counting the binaries (on the heap) info, This is done by introducing an option, bins_info, which controls this.

        Own Id: OTP-19040 Aux Id: ERIERL-1060

      diameter 2.3.1

      Fixed Bugs and Malfunctions

      • Replaced unintentional Erlang Public License 1.1 headers in some files with +

        Releases are listed in reverse chronological order, most recent first.

        diameter 2.6.1.2

        Fixed Bugs and Malfunctions

        • Fix infinite loop in diameter_dist:route_session/2 when avp other than Session-Id has zero length.

          Own Id: OTP-20242 Aux Id: PR-11331

        • Fix crash in diameter_dist:route_session/2 when Session-Id (code: 263) avp has zero length.

          Own Id: OTP-20243 Aux Id: PR-11333

        diameter 2.6.1.1

        Fixed Bugs and Malfunctions

        • Fixed return value documentation of diameter:service_info(SvcName, statistics)

          Own Id: OTP-20150 Aux Id: GH-11105, PR-11146

        diameter 2.6.1

        Improvements and New Features

        • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

          A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

          make release_docs places the documentation in the released code under the doc folder.

          make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

          The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

          Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

          Improves the source Software-Bill-of-Materials

          • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
          • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
          • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

          Own Id: OTP-19886 Aux Id: PR-10434

        diameter 2.6

        Improvements and New Features

        • Add new option 'indirect_inherits' to diameter_make:codec/2

          Own Id: OTP-19626 Aux Id: GH-8235, PR-10149

        diameter 2.5.2

        Fixed Bugs and Malfunctions

        • Added documentation about 'proxy' and 'resend' options in diameter:handle_request/3

          Own Id: OTP-19768 Aux Id: GH-10150, PR-10182

        diameter 2.5.1

        Fixed Bugs and Malfunctions

        • With this change message_cb callback will be called with updated state for processing 'ack' after 'send'.

          Own Id: OTP-19753 Aux Id: PR-9815

        diameter 2.5

        Fixed Bugs and Malfunctions

        • With this change diameter will not crash when decoding a DiameterURI without port number.

          Own Id: OTP-19620 Aux Id: PR-9321

        Improvements and New Features

        • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

          All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

          -type meter() :: integer().
          +-type foot() :: integer().

          Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

          -nominal meter() :: integer().
          +-nominal foot() :: integer().

          More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

          Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

          Own Id: OTP-19364 Aux Id: PR-9079

        • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

          Own Id: OTP-19575 Aux Id: PR-9670

        • With this change diameter will not use slave terminology

          Own Id: OTP-19621 Aux Id: PR-9786

        diameter 2.4.1.1

        Fixed Bugs and Malfunctions

        • Added documentation about 'proxy' and 'resend' options in diameter:handle_request/3

          Own Id: OTP-19768 Aux Id: GH-10150, PR-10182

        diameter 2.4.1

        Fixed Bugs and Malfunctions

        diameter 2.4

        Improvements and New Features

        • -callback attributes have been added to diameter_app and diameter_transport.

          Own Id: OTP-18783 Aux Id: PR-7699

        • The documentation has been migrated to use Markdown and ExDoc.

          Own Id: OTP-18955 Aux Id: PR-8026

        • Pick peer can now also handle request of type #href_anchor"https://github.com/erlang/otp/pull/8399" title="">PR-8399

        diameter 2.3.2.2

        Fixed Bugs and Malfunctions

        • Stop service has been made more synchronous.

          Own Id: OTP-19206 Aux Id: ERIERL-1102

        diameter 2.3.2.1

        Improvements and New Features

        • Pick peer can now also handle request of type #diameter_packet{}.

          Own Id: OTP-19090 Aux Id: PR-8399

        diameter 2.3.2

        Fixed Bugs and Malfunctions

        • Reduce the impact of calling service_info by not counting the binaries (on the heap) info, This is done by introducing an option, bins_info, which controls this.

          Own Id: OTP-19040 Aux Id: ERIERL-1060

        diameter 2.3.1

        Fixed Bugs and Malfunctions

        • Replaced unintentional Erlang Public License 1.1 headers in some files with the intended Apache License 2.0 header.

          Own Id: OTP-18815 Aux Id: PR-7780

        diameter 2.3

        Improvements and New Features

        • Replace size/1 with either tuple_size/1 or byte_size/1

          The size/1 BIF is not optimized by the JIT, and its use can result in worse types for Dialyzer.

          When one knows that the value being tested must be a tuple, tuple_size/1 should always be preferred.

          When one knows that the value being tested must be a binary, Missing in old package: /usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/dist/search_data-0F342CA6.js Missing in old package: /usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/dist/search_data-0F342CA6.js /usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/edoc_doclet_markdown.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1208)) --- old//usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/edoc_doclet_markdown.html 2026-08-21 04:00:20.724303230 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/edoc_doclet_markdown.html 2026-08-21 04:00:20.724303230 +0000 @@ -93,8 +93,8 @@

          -

          Doclet converting an edoc application to use EEP-59 and Markdown.

          This doclet has to be used together with edoc_layout_chunks.

          Example:

           1> edoc:application(example, [{preprocess, true}, {doclet, edoc_doclet_markdown},
          -       {layout, edoc_layout_chunks}]).

          It will convert the overview to Markdown and any module documentation to use -doc attributes and Markdown. Any XHTML tags in the edoc documentation that are not part of the tags supported by Erlang Documentation Format will be added as HTML tags in the Markdown.

          It does not delete the old edoc documentation.

          See also: edoc_layout_chunks.

          +

          Doclet converting an edoc application to use EEP-59 and Markdown.

          This doclet has to be used together with edoc_layout_chunks.

          Example:

           1> edoc:application(example, [{preprocess, true}, {doclet, edoc_doclet_markdown},
          +       {layout, edoc_layout_chunks}]).

          It will convert the overview to Markdown and any module documentation to use -doc attributes and Markdown. Any XHTML tags in the edoc documentation that are not part of the tags supported by Erlang Documentation Format will be added as HTML tags in the Markdown.

          It does not delete the old edoc documentation.

          See also: edoc_layout_chunks.

          /usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (6182)) --- old//usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/notes.html 2026-08-21 04:00:20.749303393 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/notes.html 2026-08-21 04:00:20.749303393 +0000 @@ -89,9 +89,9 @@ -

          This document describes the changes made to the EDoc application.

          Edoc 1.4.1

          Fixed Bugs and Malfunctions

          • Rendering of some tables in the documentation has been improved.

            Own Id: OTP-19752 Aux Id: PR-10142

          Edoc 1.4

          Fixed Bugs and Malfunctions

          • Refactor code to not rely on +nowarn_shadow_vars.

            Own Id: OTP-19574 Aux Id: PR-9678

          Improvements and New Features

          • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

            All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

            -type meter() :: integer().
            --type foot() :: integer().

            Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

            -nominal meter() :: integer().
            --nominal foot() :: integer().

            More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

            Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

            Own Id: OTP-19364 Aux Id: PR-9079

          • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

            Own Id: OTP-19575 Aux Id: PR-9670

          Edoc 1.3.2

          Fixed Bugs and Malfunctions

          • Broken links in release notes have been mended.

            Own Id: OTP-19139 Aux Id: PR-8584

          Edoc 1.3.1

          Fixed Bugs and Malfunctions

          • Fix broken makefile dependency when building HTML documentation.

            Own Id: OTP-19116 Aux Id: PR-8534

          Edoc 1.3

          Fixed Bugs and Malfunctions

          • EEP 48 doc chunks now properly include links within {@type } macros.

            Own Id: OTP-18945 Aux Id: PR-8063

          • @hidden now means hidden in EEP 48 doc chunks instead of none.

            Own Id: OTP-18946 Aux Id: PR-8063

          Improvements and New Features

          Edoc 1.2.1

          Fixed Bugs and Malfunctions

          • Emit <code> instead of <tt>.

            Own Id: OTP-18782 Aux Id: PR-7643

          Edoc 1.2

          Fixed Bugs and Malfunctions

          • Fix unused types warnings in internal edoc module.

            Own Id: OTP-17550 Aux Id: GH-5094 PR-5106

          Improvements and New Features

          • Add source file to the warning on skipped tags when generating EEP-48 style +

            This document describes the changes made to the EDoc application.

            Edoc 1.4.1

            Fixed Bugs and Malfunctions

            • Rendering of some tables in the documentation has been improved.

              Own Id: OTP-19752 Aux Id: PR-10142

            Edoc 1.4

            Fixed Bugs and Malfunctions

            • Refactor code to not rely on +nowarn_shadow_vars.

              Own Id: OTP-19574 Aux Id: PR-9678

            Improvements and New Features

            • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

              All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

              -type meter() :: integer().
              +-type foot() :: integer().

              Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

              -nominal meter() :: integer().
              +-nominal foot() :: integer().

              More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

              Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

              Own Id: OTP-19364 Aux Id: PR-9079

            • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

              Own Id: OTP-19575 Aux Id: PR-9670

            Edoc 1.3.2

            Fixed Bugs and Malfunctions

            • Broken links in release notes have been mended.

              Own Id: OTP-19139 Aux Id: PR-8584

            Edoc 1.3.1

            Fixed Bugs and Malfunctions

            • Fix broken makefile dependency when building HTML documentation.

              Own Id: OTP-19116 Aux Id: PR-8534

            Edoc 1.3

            Fixed Bugs and Malfunctions

            • EEP 48 doc chunks now properly include links within {@type } macros.

              Own Id: OTP-18945 Aux Id: PR-8063

            • @hidden now means hidden in EEP 48 doc chunks instead of none.

              Own Id: OTP-18946 Aux Id: PR-8063

            Improvements and New Features

            Edoc 1.2.1

            Fixed Bugs and Malfunctions

            • Emit <code> instead of <tt>.

              Own Id: OTP-18782 Aux Id: PR-7643

            Edoc 1.2

            Fixed Bugs and Malfunctions

            • Fix unused types warnings in internal edoc module.

              Own Id: OTP-17550 Aux Id: GH-5094 PR-5106

            Improvements and New Features

            • Add source file to the warning on skipped tags when generating EEP-48 style docs.

              Own Id: OTP-17556 Aux Id: PR-5023

            • Fix the doc chunks generators to emit documentation even if there is not module level documentation.

              Fix the doc chunks generators to respect the @hidden and @private tags properly for both modules and functions.

              Own Id: OTP-17733 Aux Id: PR-5205

            Edoc 1.1

            Improvements and New Features

            • Add option link_predefined_types that is used to create links to erlang /usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/search.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/search.html 2026-08-21 04:00:20.768303516 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/edoc-1.4.1/doc/html/search.html 2026-08-21 04:00:20.767303510 +0000 @@ -85,7 +85,7 @@

              - +

              /usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> eldap - 1.2.16 - urn:uuid:c101f17d-de02-9686-3b73-0d8b7502f58d + urn:uuid:65420503-1fff-94a5-784d-9c166e9277c8 en - 2026-08-21T03:49:55Z + 2042-09-22T17:08:56Z /usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.epub/OEBPS/eldap.xhtml differs (HTML document, ASCII text, with very long lines (1144)) --- old//usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.epub/OEBPS/eldap.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.epub/OEBPS/eldap.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -853,13 +853,13 @@ -

              Add an entry. The entry must not exist.

                add(Handle,
              +

              Add an entry. The entry must not exist.

                add(Handle,
                     "cn=Bill Valentine, ou=people, o=Example Org, dc=example, dc=com",
              -       [{"objectclass", ["person"]},
              -        {"cn", ["Bill Valentine"]},
              -        {"sn", ["Valentine"]},
              -        {"telephoneNumber", ["545 555 00"]}]
              -     )
              +
              [{"objectclass", ["person"]}, + {"cn", ["Bill Valentine"]}, + {"sn", ["Valentine"]}, + {"telephoneNumber", ["545 555 00"]}] + )
              @@ -1171,7 +1171,7 @@ -

              Creates an extensible match filter. For example,

                eldap:extensibleMatch("Bar", [{type,"sn"}, {matchingRule,"caseExactMatch"}]))

              creates a filter which performs a caseExactMatch on the attribute sn and +

              Creates an extensible match filter. For example,

                eldap:extensibleMatch("Bar", [{type,"sn"}, {matchingRule,"caseExactMatch"}]))

              creates a filter which performs a caseExactMatch on the attribute sn and matches with the value "Bar". The default value of dnAttributes is false.

              @@ -1389,9 +1389,9 @@ -

              Modify an entry.

                modify(Handle, "cn=Bill Valentine, ou=people, o=Example Org, dc=example, dc=com",
              -         [eldap:mod_replace("telephoneNumber", ["555 555 00"]),
              -	  eldap:mod_add("description", ["LDAP Hacker"]) ])
              +

              Modify an entry.

                modify(Handle, "cn=Bill Valentine, ou=people, o=Example Org, dc=example, dc=com",
              +         [eldap:mod_replace("telephoneNumber", ["555 555 00"]),
              +	  eldap:mod_add("description", ["LDAP Hacker"]) ])
              @@ -1711,8 +1711,8 @@

              Paged results is an extension to the LDAP protocol specified by RFC2696

              This function creates a control with the specified page size for use in -search/3, for example:

              Control = eldap:paged_result_control(50),
              -{ok, SearchResults} = search(Handle, [{base, "dc=example, dc=com"}], [Control]),
              +search/3, for example:

              Control = eldap:paged_result_control(50),
              +{ok, SearchResults} = search(Handle, [{base, "dc=example, dc=com"}], [Control]),
              @@ -1745,12 +1745,12 @@

              Paged results is an extension to the LDAP protocol specified by RFC2696

              This function creates a control with the specified page size and cookie for use in search/3 to retrieve the next results page.

              For example:

              PageSize = 50,
              -Control1 = eldap:paged_result_control(PageSize),
              -{ok, SearchResults1} = search(Handle, [{base, "dc=example, dc=com"}], [Control1]),
              +Control1 = eldap:paged_result_control(PageSize),
              +{ok, SearchResults1} = search(Handle, [{base, "dc=example, dc=com"}], [Control1]),
               %% retrieve the returned cookie from the search results
              -{ok, Cookie1} = eldap:paged_result_cookie(SearchResults1),
              -Control2 = eldap:paged_result_control(PageSize, Cookie1),
              -{ok, SearchResults2} = eldap:search(Handle, [{base, "dc=example,dc=com"}], [Control2]),
              +{ok, Cookie1} = eldap:paged_result_cookie(SearchResults1),
              +Control2 = eldap:paged_result_control(PageSize, Cookie1),
              +{ok, SearchResults2} = eldap:search(Handle, [{base, "dc=example,dc=com"}], [Control2]),
               %% etc
              @@ -1870,8 +1870,8 @@

              Search the directory with the supplied the SearchOptions.

              The base and filter options must be supplied. Default values: scope is wholeSubtree/0, deref is -derefAlways/0, types_only is false and timeout is 0 (meaning infinity).

                Filter = eldap:substrings("cn", [{any,"V"}]),
              -  search(Handle, [{base, "dc=example, dc=com"}, {filter, Filter}, {attributes, ["cn"]}]),

              The timeout option in the SearchOptions is for the ldap server, while the +derefAlways/0, types_only is false and timeout is 0 (meaning infinity).

                Filter = eldap:substrings("cn", [{any,"V"}]),
              +  search(Handle, [{base, "dc=example, dc=com"}, {filter, Filter}, {attributes, ["cn"]}]),

              The timeout option in the SearchOptions is for the ldap server, while the timeout in eldap:open/2 is used for each individual request in the search operation.

              /usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1144)) --- old//usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.html 2026-08-21 04:00:20.854304076 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/eldap-1.2.16/doc/html/eldap.html 2026-08-21 04:00:20.854304076 +0000 @@ -940,13 +940,13 @@ -

              Add an entry. The entry must not exist.

                add(Handle,
              +

              Add an entry. The entry must not exist.

                add(Handle,
                     "cn=Bill Valentine, ou=people, o=Example Org, dc=example, dc=com",
              -       [{"objectclass", ["person"]},
              -        {"cn", ["Bill Valentine"]},
              -        {"sn", ["Valentine"]},
              -        {"telephoneNumber", ["545 555 00"]}]
              -     )
              +
              [{"objectclass", ["person"]}, + {"cn", ["Bill Valentine"]}, + {"sn", ["Valentine"]}, + {"telephoneNumber", ["545 555 00"]}] + )
              @@ -1258,7 +1258,7 @@ -

              Creates an extensible match filter. For example,

                eldap:extensibleMatch("Bar", [{type,"sn"}, {matchingRule,"caseExactMatch"}]))

              creates a filter which performs a caseExactMatch on the attribute sn and +

              Creates an extensible match filter. For example,

                eldap:extensibleMatch("Bar", [{type,"sn"}, {matchingRule,"caseExactMatch"}]))

              creates a filter which performs a caseExactMatch on the attribute sn and matches with the value "Bar". The default value of dnAttributes is false.

              @@ -1476,9 +1476,9 @@ -

              Modify an entry.

                modify(Handle, "cn=Bill Valentine, ou=people, o=Example Org, dc=example, dc=com",
              -         [eldap:mod_replace("telephoneNumber", ["555 555 00"]),
              -	  eldap:mod_add("description", ["LDAP Hacker"]) ])
              +

              Modify an entry.

                modify(Handle, "cn=Bill Valentine, ou=people, o=Example Org, dc=example, dc=com",
              +         [eldap:mod_replace("telephoneNumber", ["555 555 00"]),
              +	  eldap:mod_add("description", ["LDAP Hacker"]) ])
              @@ -1798,8 +1798,8 @@

              Paged results is an extension to the LDAP protocol specified by RFC2696

              This function creates a control with the specified page size for use in -search/3, for example:

              Control = eldap:paged_result_control(50),
              -{ok, SearchResults} = search(Handle, [{base, "dc=example, dc=com"}], [Control]),
              +search/3, for example:

              Control = eldap:paged_result_control(50),
              +{ok, SearchResults} = search(Handle, [{base, "dc=example, dc=com"}], [Control]),
              @@ -1832,12 +1832,12 @@

              Paged results is an extension to the LDAP protocol specified by RFC2696

              This function creates a control with the specified page size and cookie for use in search/3 to retrieve the next results page.

              For example:

              PageSize = 50,
              -Control1 = eldap:paged_result_control(PageSize),
              -{ok, SearchResults1} = search(Handle, [{base, "dc=example, dc=com"}], [Control1]),
              +Control1 = eldap:paged_result_control(PageSize),
              +{ok, SearchResults1} = search(Handle, [{base, "dc=example, dc=com"}], [Control1]),
               %% retrieve the returned cookie from the search results
              -{ok, Cookie1} = eldap:paged_result_cookie(SearchResults1),
              -Control2 = eldap:paged_result_control(PageSize, Cookie1),
              -{ok, SearchResults2} = eldap:search(Handle, [{base, "dc=example,dc=com"}], [Control2]),
              +{ok, Cookie1} = eldap:paged_result_cookie(SearchResults1),
              +Control2 = eldap:paged_result_control(PageSize, Cookie1),
              +{ok, SearchResults2} = eldap:search(Handle, [{base, "dc=example,dc=com"}], [Control2]),
               %% etc
              @@ -1957,8 +1957,8 @@

              Search the directory with the supplied the SearchOptions.

              The base and filter options must be supplied. Default values: scope is wholeSubtree/0, deref is -derefAlways/0, types_only is false and timeout is 0 (meaning infinity).

                Filter = eldap:substrings("cn", [{any,"V"}]),
              -  search(Handle, [{base, "dc=example, dc=com"}, {filter, Filter}, {attributes, ["cn"]}]),

              The timeout option in the SearchOptions is for the ldap server, while the +derefAlways/0, types_only is false and timeout is 0 (meaning infinity).

                Filter = eldap:substrings("cn", [{any,"V"}]),
              +  search(Handle, [{base, "dc=example, dc=com"}, {filter, Filter}, {attributes, ["cn"]}]),

              The timeout option in the SearchOptions is for the ldap server, while the timeout in eldap:open/2 is used for each individual request in the search operation.

              /usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/ei.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (3954)) --- old//usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/ei.html 2026-08-21 04:00:20.886304285 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/ei.html 2026-08-21 04:00:20.886304285 +0000 @@ -113,30 +113,30 @@ is not of the expected type, or the data to decode is an invalid Erlang term).

              Some of the decode functions need a pre-allocated buffer. This buffer must be allocated large enough, and for non-compound types the ei_get_type() function returns the size required (notice -that for strings an extra byte is needed for the NULL-terminator).

              Data Types

              • ei_term

                typedef struct {
                +that for strings an extra byte is needed for the NULL-terminator).

                Data Types

                • ei_term

                  typedef struct {
                       char ei_type;
                       int arity;
                       int size;
                  -    union {
                  +    union {
                     long i_val;
                     double d_val;
                  -  char atom_name[MAXATOMLEN_UTF8];
                  +  char atom_name[MAXATOMLEN_UTF8];
                     erlang_pid pid;
                     erlang_port port;
                     erlang_ref ref;
                  -    } value;
                  -} ei_term;

                  Structure written by ei_decode_ei_term(). The + } value; +} ei_term;

                Structure written by ei_decode_ei_term(). The ei_type field is the type of the term which equals to what ei_get_type() sets *type to.

              • ei_x_buff - A dynamically resized buffer. It is a struct with two fields of interest for the user:

                • char *buff - Pointer to the dynamically allocated buffer.

                • int index - Offset to the next byte to write which also equals the amount of bytes currently written.

                An ei_x_buff is initialized by calling either ei_x_new() or ei_x_new_with_version(). The memory used by an initialized ei_x_buff is released by calling -ei_x_free().

              • erlang_char_encoding

                typedef enum {
                +ei_x_free().

              • erlang_char_encoding

                typedef enum {
                     ERLANG_ASCII = 1,
                     ERLANG_LATIN1 = 2,
                     ERLANG_UTF8 = 4
                -} erlang_char_encoding;

                The character encodings used for atoms. ERLANG_ASCII represents 7-bit ASCII. +} erlang_char_encoding;

      The character encodings used for atoms. ERLANG_ASCII represents 7-bit ASCII. Latin-1 and UTF-8 are different extensions of 7-bit ASCII. All 7-bit ASCII characters are valid Latin-1 and UTF-8 characters. ASCII and Latin-1 both represent each character by one byte. An UTF-8 character can consist of 1-4 @@ -146,17 +146,17 @@ process identifier.

    • erlang_port - Opaque data type representing an Erlang port identifier.

    • erlang_ref - Opaque data type representing an Erlang reference.

    • erlang_trace - Opaque data type representing an Erlang -sequential trace token.

    ei_cmp_pids()

    int ei_cmp_pids(erlang_pid *a, erlang_pid *b);

    Compare two process identifiers. The comparison is done the same way as Erlang +sequential trace token.

  • ei_cmp_pids()

    int ei_cmp_pids(erlang_pid *a, erlang_pid *b);

    Compare two process identifiers. The comparison is done the same way as Erlang does.

    Returns 0 if a and b are equal. Returns a value less than 0 if a compares as less than b. Returns a value larger than 0 if a compares as -larger than b.

    Available since OTP 23.0

    ei_cmp_ports()

    int ei_cmp_ports(erlang_port *a, erlang_port *b);

    Compare two port identifiers. The comparison is done the same way as Erlang +larger than b.

    Available since OTP 23.0

    ei_cmp_ports()

    int ei_cmp_ports(erlang_port *a, erlang_port *b);

    Compare two port identifiers. The comparison is done the same way as Erlang does.

    Returns 0 if a and b are equal. Returns a value less than 0 if a compares as less than b. Returns a value larger than 0 if a compares as -larger than b.

    Available since OTP 23.0

    ei_cmp_refs()

    int ei_cmp_refs(erlang_ref *a, erlang_ref *b);

    Compare two references. The comparison is done the same way as Erlang does.

    Returns 0 if a and b are equal. Returns a value less than 0 if a +larger than b.

    Available since OTP 23.0

    ei_cmp_refs()

    int ei_cmp_refs(erlang_ref *a, erlang_ref *b);

    Compare two references. The comparison is done the same way as Erlang does.

    Returns 0 if a and b are equal. Returns a value less than 0 if a compares as less than b. Returns a value larger than 0 if a compares as -larger than b.

    Available since OTP 23.0

    ei_decode_atom()

    int ei_decode_atom(const char *buf, int *index, char *p);

    Decodes an atom from the binary format. The NULL-terminated name of the atom -is placed at p. At most MAXATOMLEN bytes can be placed in the buffer.

    ei_decode_atom_as()

    int ei_decode_atom_as(const char *buf, int *index, char *p, int plen,
    -  erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result);

    Decodes an atom from the binary format. The NULL-terminated name of the atom +larger than b.

    Available since OTP 23.0

    ei_decode_atom()

    int ei_decode_atom(const char *buf, int *index, char *p);

    Decodes an atom from the binary format. The NULL-terminated name of the atom +is placed at p. At most MAXATOMLEN bytes can be placed in the buffer.

    ei_decode_atom_as()

    int ei_decode_atom_as(const char *buf, int *index, char *p, int plen,
    +  erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result);

    Decodes an atom from the binary format. The NULL-terminated name of the atom is placed in buffer at p of length plen bytes.

    The wanted string encoding is specified by want. The original encoding used in the binary format (Latin-1 or UTF-8) can be obtained from *was. The encoding of the resulting string (7-bit ASCII, @@ -165,13 +165,13 @@ combination like ERLANG_LATIN1|ERLANG_UTF8 or if *result turns out to be pure 7-bit ASCII (compatible with both Latin-1 and UTF-8).

    This function fails if the atom is too long for the buffer or if it cannot be represented with encoding want.

    This function was introduced in Erlang/OTP R16 as part of a first step to -support UTF-8 atoms.

    Available since OTP R16B

    ei_decode_bignum()

    int ei_decode_bignum(const char *buf, int *index, mpz_t obj);

    Decodes an integer in the binary format to a GMP mpz_t integer. To use this +support UTF-8 atoms.

    Available since OTP R16B

    ei_decode_bignum()

    int ei_decode_bignum(const char *buf, int *index, mpz_t obj);

    Decodes an integer in the binary format to a GMP mpz_t integer. To use this function, the ei library must be configured and compiled to use the GMP -library.

    ei_decode_binary()

    int ei_decode_binary(const char *buf, int *index, void *p, long *len);

    Decodes a binary from the binary format. Parameter len is set to the actual +library.

    ei_decode_binary()

    int ei_decode_binary(const char *buf, int *index, void *p, long *len);

    Decodes a binary from the binary format. Parameter len is set to the actual size of the binary. Notice that ei_decode_binary() assumes that there is enough room for the binary. The size required can be fetched by -ei_get_type().

    ei_decode_bitstring()

    int ei_decode_bitstring(const char *buf, int *index, const char **pp,
    -  unsigned int *bitoffsp, size_t *nbitsp);

    Decodes a bit string from the binary format.

    Data Types

    ei_gethostbyaddr()

    ei_gethostbyaddr_r()

    ei_gethostbyname()

    ei_gethostbyname_r()

    struct hostent * ei_gethostbyaddr(const char *addr, int len, int type);
    struct hostent * ei_gethostbyaddr_r(const char *addr, int length,  int type,
    -  struct hostent *hostp, char *buffer,   int buflen,  int *h_errnop);
    struct hostent * ei_gethostbyname(const char *name);
    struct hostent * ei_gethostbyname_r(const char *name,  struct hostent *hostp,
    -  char *buffer,  int buflen,  int *h_errnop);

    Convenience functions for some common name lookup functions.

    ei_accept()

    int ei_accept(ei_cnode *ec, int listensock, ErlConnect *conp);

    Used by a server process to accept a connection from a client process.

    ei_gethostbyaddr()

    ei_gethostbyaddr_r()

    ei_gethostbyname()

    ei_gethostbyname_r()

    struct hostent * ei_gethostbyaddr(const char *addr, int len, int type);
    struct hostent * ei_gethostbyaddr_r(const char *addr, int length,  int type,
    +  struct hostent *hostp, char *buffer,   int buflen,  int *h_errnop);
    struct hostent * ei_gethostbyname(const char *name);
    struct hostent * ei_gethostbyname_r(const char *name,  struct hostent *hostp,
    +  char *buffer,  int buflen,  int *h_errnop);

    Convenience functions for some common name lookup functions.

    ei_accept()

    int ei_accept(ei_cnode *ec, int listensock, ErlConnect *conp);

    Used by a server process to accept a connection from a client process.

    On success, conp is filled in with the address and node name of the connecting client and a file descriptor is returned. On failure, ERL_ERROR is returned -and erl_errno is set to EIO.

    ei_accept_tmo()

    int ei_accept_tmo(ei_cnode *ec, int listensock, ErlConnect *conp, unsigned timeout_ms);

    Equivalent to ei_accept with an optional time-out argument, see the -description at the beginning of this manual page.

    ei_close_connection()

    int ei_close_connection(int fd);

    Closes a previously opened connection or listen socket.

    Available since OTP 21.3

    ei_connect()

    ei_xconnect()

    ei_connect_host_port()

    Available since OTP 23.0

    ei_xconnect_host_port()

    int ei_connect(ei_cnode* ec, char *nodename);
    int ei_xconnect(ei_cnode* ec, Erl_IpAddr adr, char *alivename);
    int ei_connect_host_port(ei_cnode* ec, char *hostname, int port);
    int ei_xconnect_host_port(ei_cnode* ec, Erl_IpAddr adr, int port);

    Sets up a connection to an Erlang node.

    ei_xconnect() requires the IP address of the remote host and the alive name of +and erl_errno is set to EIO.

    ei_accept_tmo()

    int ei_accept_tmo(ei_cnode *ec, int listensock, ErlConnect *conp, unsigned timeout_ms);

    Equivalent to ei_accept with an optional time-out argument, see the +description at the beginning of this manual page.

    ei_close_connection()

    int ei_close_connection(int fd);

    Closes a previously opened connection or listen socket.

    Available since OTP 21.3

    ei_connect()

    ei_xconnect()

    ei_connect_host_port()

    Available since OTP 23.0

    ei_xconnect_host_port()

    int ei_connect(ei_cnode* ec, char *nodename);
    int ei_xconnect(ei_cnode* ec, Erl_IpAddr adr, char *alivename);
    int ei_connect_host_port(ei_cnode* ec, char *hostname, int port);
    int ei_xconnect_host_port(ei_cnode* ec, Erl_IpAddr adr, int port);

    Sets up a connection to an Erlang node.

    ei_xconnect() requires the IP address of the remote host and the alive name of the remote node to be specified. ei_connect() provides an alternative interface and determines the information from the node name provided. The ei_xconnect_host_port() function provides yet another alternative that will @@ -171,16 +171,16 @@ #define IP_ADDR "150.236.14.75" /*** Variant 1 ***/ -int fd = ei_connect(&ec, NODE); +int fd = ei_connect(&ec, NODE); /*** Variant 2 ***/ struct in_addr addr; -addr.s_addr = inet_addr(IP_ADDR); -fd = ei_xconnect(&ec, &addr, ALIVE);

    Available since OTP 23.0

    ei_connect_init()

    ei_connect_init_ussi()

    Available since OTP 21.3

    ei_connect_xinit()

    ei_connect_xinit_ussi()

    int ei_connect_init(ei_cnode* ec, const char* this_node_name, const char *cookie, unsigned creation);
    int ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name, const char *cookie,
    -  unsigned creation, ei_socket_callbacks *cbs, int cbs_sz, void *setup_context);
    int ei_connect_xinit(ei_cnode* ec, const char *thishostname, const char *thisalivename,
    -  const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, unsigned creation);
    int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname, const char *thisalivename,
    +addr.s_addr = inet_addr(IP_ADDR);
    +fd = ei_xconnect(&ec, &addr, ALIVE);

    Available since OTP 23.0

    ei_connect_init()

    ei_connect_init_ussi()

    Available since OTP 21.3

    ei_connect_xinit()

    ei_connect_xinit_ussi()

    int ei_connect_init(ei_cnode* ec, const char* this_node_name, const char *cookie, unsigned creation);
    int ei_connect_init_ussi(ei_cnode* ec, const char* this_node_name, const char *cookie,
    +  unsigned creation, ei_socket_callbacks *cbs, int cbs_sz, void *setup_context);
    int ei_connect_xinit(ei_cnode* ec, const char *thishostname, const char *thisalivename,
    +  const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, unsigned creation);
    int ei_connect_xinit_ussi(ei_cnode* ec, const char *thishostname, const char *thisalivename,
       const char *thisnodename, Erl_IpAddr thisipaddr, const char *cookie, unsigned creation,
    -  ei_socket_callbacks *cbs, int cbs_sz, void *setup_context);

    Initializes the ec structure, to identify the node name and cookie of the + ei_socket_callbacks *cbs, int cbs_sz, void *setup_context);

    Initializes the ec structure, to identify the node name and cookie of the server. One of them must be called before other functions that works on the ei_cnode type or a file descriptor associated with a connection to another node is used.

    The return value is the same as for ei_receive.

    ei_receive_msg_tmo()

    ei_xreceive_msg_tmo()

    int ei_receive_msg_tmo(int fd, erlang_msg* msg, ei_x_buff* x, unsigned imeout_ms);
    int ei_xreceive_msg_tmo(int fd, erlang_msg* msg, ei_x_buff* x, unsigned timeout_ms);

    Equivalent to ei_receive_msg and ei_xreceive_msg with an optional time-out +argument, see the description at the beginning of this manual page.

    ei_receive_tmo()

    int ei_receive_tmo(int fd, unsigned char* bufp, int bufsize, unsigned timeout_ms);

    Equivalent to ei_receive with an optional time-out argument, see the +description at the beginning of this manual page.

    ei_reg_send()

    int ei_reg_send(ei_cnode* ec, int fd, char* server_name, char* buf, int len);

    Sends an Erlang term to a registered process.

    Returns 0 if successful, otherwise -1. In the latter case it sets erl_errno to EIO.

    Example:

    Send the atom "ok" to the process "worker":

    ei_x_buff x;
    -ei_x_new_with_version(&x);
    -ei_x_encode_atom(&x, "ok");
    /usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_interface.epub/OEBPS/ei_global.xhtml differs (HTML document, ASCII text, with very long lines (3119))
    --- old//usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_interface.epub/OEBPS/ei_global.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_interface.epub/OEBPS/ei_global.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -22,14 +22,14 @@
     kernel:global.

    Notice that the functions below perform an RPC using an open file descriptor provided by the caller. This file descriptor must not be used for other traffic during the global operation, as the function can then receive unexpected data -and fail.

    ei_global_names()

    char **ei_global_names(ei_cnode *ec, int fd, int *count);

    Retrieves a list of all known global names.

    • ec is the ei_cnode representing the current cnode.
    • fd is an open descriptor to an Erlang connection.
    • count is the address of an integer, or NULL. If count is not NULL, it +and fail.

      ei_global_names()

      char **ei_global_names(ei_cnode *ec, int fd, int *count);

      Retrieves a list of all known global names.

      • ec is the ei_cnode representing the current cnode.
      • fd is an open descriptor to an Erlang connection.
      • count is the address of an integer, or NULL. If count is not NULL, it is set by the function to the number of names found.

      On success, the function returns an array of strings, each containing a single registered name, and sets count to the number of names found. The array is terminated by a single NULL pointer. On failure, the function returns NULL and count is not modified.

      Note

      It is the caller's responsibility to free the array afterwards. It has been allocated by the function with a single call to malloc(), so a single -free() is all that is necessary.

      Available since OTP 23.0

      ei_global_register()

      int ei_global_register(int fd, const char *name, erlang_pid *self);

      Registers a name in global.

      • fd is an open descriptor to an Erlang connection.
      • name is the name to register in global.
      • pid is the pid that is to be associated with name. This value is returned -by global when processes request the location of name.

      Returns 0 on success, otherwise -1.

      Available since OTP 23.0

      ei_global_unregister()

      int ei_global_unregister(ei_cnode *ec, int fd, const char *name);

      Unregisters a name from global.

      • ec is the ei_cnode representing the current cnode.
      • fd is an open descriptor to an Erlang connection.
      • name is the name to unregister from global.

      Returns 0 on success, otherwise -1.

      Available since OTP 23.0

      ei_global_whereis()

      int ei_global_whereis(ei_cnode *ec, int fd, const char *name, erlang_pid* pid, char *node);

      Looks up a name in global.

      • ec is the ei_cnode representing the current cnode.
      • fd is an open descriptor to an Erlang connection.
      • name is the name that is to be looked up in global.

      The pid parameter is a pointer to a erlang_pid that the function will update +free() is all that is necessary.

      Available since OTP 23.0

      ei_global_register()

      int ei_global_register(int fd, const char *name, erlang_pid *self);

      Registers a name in global.

      • fd is an open descriptor to an Erlang connection.
      • name is the name to register in global.
      • pid is the pid that is to be associated with name. This value is returned +by global when processes request the location of name.

      Returns 0 on success, otherwise -1.

      Available since OTP 23.0

      ei_global_unregister()

      int ei_global_unregister(ei_cnode *ec, int fd, const char *name);

      Unregisters a name from global.

      • ec is the ei_cnode representing the current cnode.
      • fd is an open descriptor to an Erlang connection.
      • name is the name to unregister from global.

      Returns 0 on success, otherwise -1.

      Available since OTP 23.0

      ei_global_whereis()

      int ei_global_whereis(ei_cnode *ec, int fd, const char *name, erlang_pid* pid, char *node);

      Looks up a name in global.

      • ec is the ei_cnode representing the current cnode.
      • fd is an open descriptor to an Erlang connection.
      • name is the name that is to be looked up in global.

      The pid parameter is a pointer to a erlang_pid that the function will update with the pid associated with the global name, if successful.

      If node is not NULL, it is a pointer to a buffer where the function can fill in the name of the node where name is found. node can be passed directly to ei_connect() if necessary.

      On success, the function returns 0, updates the erlang_pid pointed to by the /usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_interface.epub/OEBPS/ei_users_guide.xhtml differs (HTML document, ASCII text, with very long lines (971)) --- old//usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_interface.epub/OEBPS/ei_users_guide.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_interface.epub/OEBPS/ei_users_guide.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -46,25 +46,25 @@ Erlang.

      The Erl_Interface library supports this activity. It has several C functions that create and manipulate Erlang data structures. The following example shows how to create and encode an Erlang tuple {tobbe,3928}:

      ei_x_buff buf;
      -ei_x_new(&buf);
      +ei_x_new(&buf);
       int i = 0;
      -ei_x_encode_tuple_header(&buf, 2);
      -ei_x_encode_atom(&buf, "tobbe");
      -ei_x_encode_long(&buf, 3928);

      For a complete description, see the ei module.

      Building Terms

      The previous example can be simplified by using the +ei_x_encode_tuple_header(&buf, 2); +ei_x_encode_atom(&buf, "tobbe"); +ei_x_encode_long(&buf, 3928);

    For a complete description, see the ei module.

    Building Terms

    The previous example can be simplified by using the ei_x_format_wo_ver function to create an Erlang term:

    ei_x_buff buf;
    -ei_x_new(&buf);
    -ei_x_format_wo_ver(&buf, "{~a,~i}", "tobbe", 3928);

    For a complete description of the different format directives, see the the +ei_x_new(&buf); +ei_x_format_wo_ver(&buf, "{~a,~i}", "tobbe", 3928);

    For a complete description of the different format directives, see the the ei_x_format_wo_ver function.

    The following example is more complex:

    ei_x_buff buf;
     int i = 0;
    -ei_x_new(&buf);
    -ei_x_format_wo_ver(&buf,
    +ei_x_new(&buf);
    +ei_x_format_wo_ver(&buf,
                        "[{name,~a},{age,~i},{data,[{adr,~s,~i}]}]",
                        "madonna",
                        21,
    -                  "E-street", 42);
    -ei_print_term(stdout, buf.buff, &i);
    -ei_x_free(&buf);

    As in the previous examples, it is your responsibility to free the memory + "E-street", 42); +ei_print_term(stdout, buf.buff, &i); +ei_x_free(&buf);

    As in the previous examples, it is your responsibility to free the memory allocated for Erlang terms. In this example, ei_x_free() ensures that the data pointed to by buf is released.

    Connecting to a Distributed Erlang Node

    To connect to a distributed Erlang node, you must first initialize the connection routine with one of the @@ -74,18 +74,18 @@ char *cookie="a secret cookie string"; /* An example */ const char* node_name = "einode@durin"; const char *cookie = NULL; -short creation = time(NULL) + 1; +short creation = time(NULL) + 1; ei_cnode ec; -ei_connect_init(&ec, +ei_connect_init(&ec, node_name, cookie, - creation);

    For more information, see the ei_connect module.

    After initialization, you set up the connection to the Erlang node. To specify + creation);

    For more information, see the ei_connect module.

    After initialization, you set up the connection to the Erlang node. To specify the Erlang node you want to connect to, use the ei_connect_*() family of functions. The following example sets up the connection and is to result in a valid socket file descriptor:

    int sockfd;
     const char* node_name = "einode@durin"; /* An example */
    -if ((sockfd = ei_connect(&ec, nodename)) < 0)
    -  fprintf(stderr, "ERROR: ei_connect failed");

    Using EPMD

    erts:epmd is the Erlang Port Mapper Daemon. +if ((sockfd = ei_connect(&ec, nodename)) < 0) + fprintf(stderr, "ERROR: ei_connect failed");

    Using EPMD

    erts:epmd is the Erlang Port Mapper Daemon. Distributed Erlang nodes register with epmd on the local host to indicate to other nodes that they exist and can accept connections. epmd maintains a register of node and port number information, and when a node wishes to connect @@ -94,7 +94,7 @@ connection is first made to epmd and, if the node is known, a connection is then made to the Erlang node.

    C nodes can also register themselves with epmd if they want other nodes in the system to be able to find and connect to them.

    Before registering with epmd, you must first create a listen socket and bind -it to a port. Then:

    int pub = ei_publish(&ec, port);

    pub is a file descriptor now connected to epmd. epmd monitors the other +it to a port. Then:

    int pub = ei_publish(&ec, port);

    pub is a file descriptor now connected to epmd. epmd monitors the other end of the connection. If it detects that the connection has been closed, the node becomes unregistered. So, if you explicitly close the descriptor or if your node fails, it becomes unregistered from epmd.

    Notice that on some systems a failed node is not detected by this mechanism, as @@ -105,13 +105,13 @@ easier to send a message to a registered name, as it avoids the problem of finding a suitable pid.

    Use one of the following two functions to receive messages:

    Example of Sending Messages

    In the following example, {Pid, hello_world} is sent to a registered process my_server:

    ei_x_buff buf;
    -ei_x_new_with_version(&buf);
    +ei_x_new_with_version(&buf);
     
    -ei_x_encode_tuple_header(&buf, 2);
    -ei_x_encode_pid(&buf, ei_self(ec));
    -ei_x_encode_atom(&buf, "Hello world");
    +ei_x_encode_tuple_header(&buf, 2);
    +ei_x_encode_pid(&buf, ei_self(ec));
    +ei_x_encode_atom(&buf, "Hello world");
     
    -ei_reg_send(&ec, fd, "my_server", buf.buff, buf.index);

    The first element of the tuple that is sent is your own pid. This enables +ei_reg_send(&ec, fd, "my_server", buf.buff, buf.index);

    The first element of the tuple that is sent is your own pid. This enables my_server to reply. For more information about the primitives, see the ei_connect module.

    Example of Receiving Messages

    In this example, {Pid, Something} is received.

    erlang_msg msg;
     int index = 0;
    @@ -119,24 +119,24 @@
     int arity = 0;
     erlang_pid pid;
     ei_x_buff buf;
    -ei_x_new(&buf);
    -for (;;) {
    -  int got = ei_xreceive_msg(fd, &msg, &x);
    -  if (got == ERL_TICK)
    +ei_x_new(&buf);
    +for (;;) {
    +  int got = ei_xreceive_msg(fd, &msg, &x);
    +  if (got == ERL_TICK)
         continue;
    -  if (got == ERL_ERROR) {
    -    fprintf(stderr, "ei_xreceive_msg, got==%d", got);
    -    exit(1);
    -  }
    +  if (got == ERL_ERROR) {
    +    fprintf(stderr, "ei_xreceive_msg, got==%d", got);
    +    exit(1);
    +  }
       break;
    -}
    -ei_decode_version(buf.buff, &index, &version);
    -ei_decode_tuple_header(buf.buff, &index, &arity);
    -if (arity != 2) {
    -  fprintf(stderr, "got wrong message");
    -  exit(1);
    -}
    -ei_decode_pid(buf.buff, &index, &pid);

    To provide robustness, a distributed Erlang node occasionally polls all its +} +ei_decode_version(buf.buff, &index, &version); +ei_decode_tuple_header(buf.buff, &index, &arity); +if (arity != 2) { + fprintf(stderr, "got wrong message"); + exit(1); +} +ei_decode_pid(buf.buff, &index, &pid);

    To provide robustness, a distributed Erlang node occasionally polls all its connected neighbors in an attempt to detect failed nodes or communication links. A node that receives such a message is expected to respond immediately with an ERL_TICK message. This is done automatically by ei_xreceive_msg(). However, @@ -148,19 +148,19 @@ a remote node and is called a remote procedure call.

    The following example checks if a specific Erlang process is alive:

    int index = 0, is_alive;
     ei_x_buff args, result;
     
    -ei_x_new(&result);
    -ei_x_new(&args);
    -ei_x_encode_list_header(&args, 1);
    -ei_x_encode_pid(&args, &check_pid);
    -ei_x_encode_empty_list(&args);
    -
    -if (ei_rpc(&ec, fd, "erlang", "is_process_alive",
    -           args.buff, args.index, &result) < 0)
    -    handle_error();
    -
    -if (ei_decode_version(result.buff, &index) < 0
    -    || ei_decode_bool(result.buff, &index, &is_alive) < 0)
    -    handle_error();

    For more information about ei_rpc() and its companions ei_rpc_to() and +ei_x_new(&result); +ei_x_new(&args); +ei_x_encode_list_header(&args, 1); +ei_x_encode_pid(&args, &check_pid); +ei_x_encode_empty_list(&args); + +if (ei_rpc(&ec, fd, "erlang", "is_process_alive", + args.buff, args.index, &result) < 0) + handle_error(); + +if (ei_decode_version(result.buff, &index) < 0 + || ei_decode_bool(result.buff, &index, &is_alive) < 0) + handle_error();

    For more information about ei_rpc() and its companions ei_rpc_to() and ei_rpc_from(), see the ei_connect module.

    Using Global Names

    A C node has access to names registered through the global module in Kernel. Names can be looked up, allowing the C node to send messages to named Erlang services. C nodes can also register global names, allowing them to provide named @@ -171,32 +171,32 @@ int count; int i; -names = ei_global_names(&ec,fd,&count); +names = ei_global_names(&ec,fd,&count); -if (names) - for (i=0; i<count; i++) - printf("%s\n",names[i]); +if (names) + for (i=0; i<count; i++) + printf("%s\n",names[i]); -free(names);

    ei_global_names allocates and returns a buffer +free(names);

    ei_global_names allocates and returns a buffer containing all the names known to the global module in Kernel. count is initialized to indicate the number of names in the array. The array of strings in names is terminated by a NULL pointer, so it is not necessary to use count to determine when the last name is reached.

    It is the caller's responsibility to free the array. ei_global_names allocates the array and all the strings using a single call to malloc(), so free(names) is all that is necessary.

    To look up one of the names:

    ETERM *pid;
    -char node[256];
    +char node[256];
     erlang_pid the_pid;
     
    -if (ei_global_whereis(&ec,fd,"schedule",&the_pid,node) < 0)
    -   fprintf(stderr, "ei_global_whereis error\n");

    If "schedule" is known to the global module in Kernel, an Erlang pid is +if (ei_global_whereis(&ec,fd,"schedule",&the_pid,node) < 0) + fprintf(stderr, "ei_global_whereis error\n");

    If "schedule" is known to the global module in Kernel, an Erlang pid is written to the_pid. This pid that can be used to send messages to the schedule service. Also, node is initialized to contain the name of the node where the service is registered, so that you can make a connection to it by simply passing the variable to ei_connect.

    Before registering a name, you should already have registered your port number with epmd. This is not strictly necessary, but if you neglect to do so, then /usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_interface.epub/OEBPS/ei.xhtml differs (HTML document, ASCII text, with very long lines (3495)) --- old//usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_interface.epub/OEBPS/ei.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/erl_interface-5.7.0.1/doc/html/erl_interface.epub/OEBPS/ei.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -41,30 +41,30 @@ is not of the expected type, or the data to decode is an invalid Erlang term).

    Some of the decode functions need a pre-allocated buffer. This buffer must be allocated large enough, and for non-compound types the ei_get_type() function returns the size required (notice -that for strings an extra byte is needed for the NULL-terminator).

    Data Types

    ei_cmp_pids()

    int ei_cmp_pids(erlang_pid *a, erlang_pid *b);

    Compare two process identifiers. The comparison is done the same way as Erlang +sequential trace token.

    ei_cmp_pids()

    int ei_cmp_pids(erlang_pid *a, erlang_pid *b);

    Compare two process identifiers. The comparison is done the same way as Erlang does.

    Returns 0 if a and b are equal. Returns a value less than 0 if a compares as less than b. Returns a value larger than 0 if a compares as -larger than b.

    Available since OTP 23.0

    ei_cmp_ports()

    int ei_cmp_ports(erlang_port *a, erlang_port *b);

    Compare two port identifiers. The comparison is done the same way as Erlang +larger than b.

    Available since OTP 23.0

    ei_cmp_ports()

    int ei_cmp_ports(erlang_port *a, erlang_port *b);

    Compare two port identifiers. The comparison is done the same way as Erlang does.

    Returns 0 if a and b are equal. Returns a value less than 0 if a compares as less than b. Returns a value larger than 0 if a compares as -larger than b.

    Available since OTP 23.0

    ei_cmp_refs()

    int ei_cmp_refs(erlang_ref *a, erlang_ref *b);

    Compare two references. The comparison is done the same way as Erlang does.

    Returns 0 if a and b are equal. Returns a value less than 0 if a +larger than b.

    Available since OTP 23.0

    ei_cmp_refs()

    int ei_cmp_refs(erlang_ref *a, erlang_ref *b);

    Compare two references. The comparison is done the same way as Erlang does.

    Returns 0 if a and b are equal. Returns a value less than 0 if a compares as less than b. Returns a value larger than 0 if a compares as -larger than b.

    Available since OTP 23.0

    ei_decode_atom()

    int ei_decode_atom(const char *buf, int *index, char *p);

    Decodes an atom from the binary format. The NULL-terminated name of the atom -is placed at p. At most MAXATOMLEN bytes can be placed in the buffer.

    ei_decode_atom_as()

    int ei_decode_atom_as(const char *buf, int *index, char *p, int plen,
    -  erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result);

    Decodes an atom from the binary format. The NULL-terminated name of the atom +larger than b.

    Available since OTP 23.0

    ei_decode_atom()

    int ei_decode_atom(const char *buf, int *index, char *p);

    Decodes an atom from the binary format. The NULL-terminated name of the atom +is placed at p. At most MAXATOMLEN bytes can be placed in the buffer.

    ei_decode_atom_as()

    int ei_decode_atom_as(const char *buf, int *index, char *p, int plen,
    +  erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result);

    Decodes an atom from the binary format. The NULL-terminated name of the atom is placed in buffer at p of length plen bytes.

    The wanted string encoding is specified by want. The original encoding used in the binary format (Latin-1 or UTF-8) can be obtained from *was. The encoding of the resulting string (7-bit ASCII, @@ -93,13 +93,13 @@ combination like ERLANG_LATIN1|ERLANG_UTF8 or if *result turns out to be pure 7-bit ASCII (compatible with both Latin-1 and UTF-8).

    This function fails if the atom is too long for the buffer or if it cannot be represented with encoding want.

    This function was introduced in Erlang/OTP R16 as part of a first step to -support UTF-8 atoms.

    Available since OTP R16B

    ei_decode_bignum()

    int ei_decode_bignum(const char *buf, int *index, mpz_t obj);

    Decodes an integer in the binary format to a GMP mpz_t integer. To use this +support UTF-8 atoms.

    Available since OTP R16B

    ei_decode_bignum()

    int ei_decode_bignum(const char *buf, int *index, mpz_t obj);

    Decodes an integer in the binary format to a GMP mpz_t integer. To use this function, the ei library must be configured and compiled to use the GMP -library.

    ei_decode_binary()

    int ei_decode_binary(const char *buf, int *index, void *p, long *len);

    Decodes a binary from the binary format. Parameter len is set to the actual +library.

    ei_decode_binary()

    int ei_decode_binary(const char *buf, int *index, void *p, long *len);

    Decodes a binary from the binary format. Parameter len is set to the actual size of the binary. Notice that ei_decode_binary() assumes that there is enough room for the binary. The size required can be fetched by -ei_get_type().

    ei_decode_bitstring()

    int ei_decode_bitstring(const char *buf, int *index, const char **pp,
    -  unsigned int *bitoffsp, size_t *nbitsp);

    Decodes a bit string from the binary format.

    /usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/httpd.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2672)) --- old//usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/httpd.html 2026-08-21 04:00:21.545308574 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/httpd.html 2026-08-21 04:00:21.545308574 +0000 @@ -153,36 +153,36 @@ level error under the hierarchical logger domain: [otp, inets, httpd, ServerID, error] The built in logger formatting function produces log entries from the error -reports:

    #{server_name => string()
    +reports:

    #{server_name => string()
       protocol => internal | 'TCP' | 'TLS' | 'HTTP',
       transport => "TCP" | "TLS", %% Present when protocol = 'HTTP'
    -  uri => string(), %% Present when protocol = 'HTTP' and URI is valid
    -  peer => inet:peername(),
    -  host => inet:hostname(),
    -  reason => term()
    -}

    An example of a log entry with only default settings of logger

    =ERROR REPORT==== 9-Oct-2019::09:33:27.350235 ===
    +  uri => string(), %% Present when protocol = 'HTTP' and URI is valid
    +  peer => inet:peername(),
    +  host => inet:hostname(),
    +  reason => term()
    +}

    An example of a log entry with only default settings of logger

    =ERROR REPORT==== 9-Oct-2019::09:33:27.350235 ===
        Server: My Server
      Protocol: HTTP
     Transport: TLS
           URI: /not_there
          Host: 127.0.1.1:80
          Peer: 127.0.0.1:45253
    -   Reason: [{statuscode,404},{description,"Object Not Found"}]

    Using this option makes mod_log and mod_disk_log error logs redundant.

    Add the filter

    {fun logger_filters:domain/2,
    -    {log,equal,[otp,inets, httpd, ServerID, error]}

    to appropriate logger handler to handle the events. For example to write the + Reason: [{statuscode,404},{description,"Object Not Found"}]

    Using this option makes mod_log and mod_disk_log error logs redundant.

    Add the filter

    {fun logger_filters:domain/2,
    +    {log,equal,[otp,inets, httpd, ServerID, error]}

    to appropriate logger handler to handle the events. For example to write the error log from an httpd server with a ServerID of my_server to a file -you can use the following sys.config:

    [{kernel,
    - [{logger,
    -  [{handler, http_error_test, logger_std_h,
    -    #{config => #{ file => "log/http_error.log" },
    -      filters => [{inets_httpd, {fun logger_filters:domain/2,
    -                                 {log, equal,
    -                                  [otp, inets, httpd, my_server, error]
    -                                 }}}],
    -      filter_default => stop }}]}]}].

    or if you want to add it to the default logger via an API:

    logger:add_handler_filter(default,
    +you can use the following sys.config:

    [{kernel,
    + [{logger,
    +  [{handler, http_error_test, logger_std_h,
    +    #{config => #{ file => "log/http_error.log" },
    +      filters => [{inets_httpd, {fun logger_filters:domain/2,
    +                                 {log, equal,
    +                                  [otp, inets, httpd, my_server, error]
    +                                 }}}],
    +      filter_default => stop }}]}]}].

    or if you want to add it to the default logger via an API:

    logger:add_handler_filter(default,
                               inets_httpd,
    -                          {fun logger_filters:domain/2,
    -                           {log, equal,
    -                            [otp, inets, httpd, my_server, error]}}).
  • {log_format, common | combined}
    Defines if access logs are to be written according to the common log format + {fun logger_filters:domain/2, + {log, equal, + [otp, inets, httpd, my_server, error]}}).

  • {log_format, common | combined}
    Defines if access logs are to be written according to the common log format or the extended common log format. The common format is one line looking like this: remotehost rfc931 authuser [date] "request" status bytes.

    Here:

    • remotehost - Remote.

    • rfc931 - The remote username of the client (RFC 931).

    • authuser - The username used for authentication.

    • [date] - Date and time of the request @@ -192,18 +192,18 @@ remotehost rfc931 authuser [date] "request" status bytes "referer" "user_agent"

      In addition to the earlier:

      • "referer" - The URL the client was on before requesting the URL (if it could not be determined, a minus sign is placed in this field).

      • "user_agent" - The software the client claims to be using (if it could not be determined, a minus sign is placed in this field).

      This affects the access logs written by mod_log and mod_disk_log.

    • {error_log_format, pretty | compact}
      Default is pretty. If the error log is meant to be read directly by a human, -pretty is the best option.

      pretty has a format corresponding to:

      io:format("[~s] ~s, reason: ~n ~p ~n~n", [Date, Msg, Reason]).

      compact has a format corresponding to:

      io:format("[~s] ~s, reason: ~w ~n", [Date, Msg, Reason]).

      This affects the error logs written by mod_log and mod_disk_log.

    URL Aliasing Properties - Requires mod_alias

    • {alias, {Alias, RealName}}
      Alias = string() and RealName = string(). alias allows documents to be +pretty is the best option.

      pretty has a format corresponding to:

      io:format("[~s] ~s, reason: ~n ~p ~n~n", [Date, Msg, Reason]).

      compact has a format corresponding to:

      io:format("[~s] ~s, reason: ~w ~n", [Date, Msg, Reason]).

      This affects the error logs written by mod_log and mod_disk_log.

    URL Aliasing Properties - Requires mod_alias

    • {alias, {Alias, RealName}}
      Alias = string() and RealName = string(). alias allows documents to be stored in the local file system instead of the document_root location. URLs with a path beginning with url-path is mapped to local files beginning with -directory-filename, for example:

      {alias, {"/image", "/ftp/pub/image"}}

      Access to http://your.server.org/image/foo.gif would refer to the file +directory-filename, for example:

      {alias, {"/image", "/ftp/pub/image"}}

      Access to http://your.server.org/image/foo.gif would refer to the file /ftp/pub/image/foo.gif.

    • {re_write, {Re, Replacement}}
      Re = string() and Replacement = string(). re_write allows documents to be stored in the local file system instead of the document_root location. URLs are rewritten by re:replace/3 to produce a path in the local -file-system, for example:

      {re_write, {"^/[~]([^/]+)(.*)$", "/home/\\1/public\\2"}}

      Access to http://your.server.org/~bob/foo.gif would refer to the file +file-system, for example:

      {re_write, {"^/[~]([^/]+)(.*)$", "/home/\\1/public\\2"}}

      Access to http://your.server.org/~bob/foo.gif would refer to the file /home/bob/public/foo.gif.

    • {directory_index, [string()]}
      directory_index specifies a list of resources to look for if a client requests a directory using a / at the end of the directory name. file depicts the name of a file in the directory. Several files can be given, in -which case the server returns the first it finds, for example:

      {directory_index, ["index.html", "welcome.html"]}

      Access to http://your.server.org/docs/ would return +which case the server returns the first it finds, for example:

      {directory_index, ["index.html", "welcome.html"]}

      Access to http://your.server.org/docs/ would return http://your.server.org/docs/index.html or http://your.server.org/docs/welcome.html if index.html does not exist.

    CGI Properties - Requires mod_cgi

    • {script_alias, {Alias, RealName}}
      Alias = string() and RealName = string(). Have the same behavior as property alias, except that they also mark the target directory as @@ -228,9 +228,9 @@ method. The method is either GET or POST, as defined in RFC 1945. It propagates the URL and file path of the requested document using the standard CGI PATH_INFO and -PATH_TRANSLATED environment variables.

      Example:

      {script, {"PUT", "/cgi-bin/put"}}

    ESI Properties - Requires mod_esi

    • {erl_script_alias, {URLPath, [AllowedModule]}}
      URLPath = string() and AllowedModule = atom(). erl_script_alias marks +PATH_TRANSLATED environment variables.

      Example:

      {script, {"PUT", "/cgi-bin/put"}}

    ESI Properties - Requires mod_esi

    • {erl_script_alias, {URLPath, [AllowedModule]}}
      URLPath = string() and AllowedModule = atom(). erl_script_alias marks all URLs matching url-path as erl scheme scripts. A matching URL is mapped -into a specific module and function, for example:

      {erl_script_alias, {"/cgi-bin/example", [httpd_example]}}

      A request to http://your.server.org/cgi-bin/example/httpd_example:yahoo would +into a specific module and function, for example:

      {erl_script_alias, {"/cgi-bin/example", [httpd_example]}}

      A request to http://your.server.org/cgi-bin/example/httpd_example:yahoo would refer to httpd_example:yahoo/3 or, if that does not exist, httpd_example:yahoo/2 and http://your.server.org/cgi-bin/example/other:yahoo would not be allowed to execute.

    • {erl_script_nocache, boolean()}
      If erl_script_nocache is set to true, the server adds HTTP header fields @@ -262,7 +262,7 @@ relative to the server_root.

    • {transfer_disk_log_size, {MaxBytes, MaxFiles}}
      MaxBytes = integer() and MaxFiles = integer(). Defines the properties of the disk_log access log file. This file is of type wrap log and max bytes is written to each file and max files is used before the first file is -truncated and reused.

    Authentication Properties - Requires mod_auth

    {directory, {path(), [{property(), term()}]}}

    The properties for directories are as follows:

    • {allow_from, all | [RegxpHostString]}
      Defines a set of hosts to be granted access to a given directory, for example:

      {allow_from, ["123.34.56.11", "150.100.23"]}

      The host 123.34.56.11 and all machines on the 150.100.23 subnet are +truncated and reused.

    Authentication Properties - Requires mod_auth

    {directory, {path(), [{property(), term()}]}}

    The properties for directories are as follows:

    • {allow_from, all | [RegxpHostString]}
      Defines a set of hosts to be granted access to a given directory, for example:

      {allow_from, ["123.34.56.11", "150.100.23"]}

      The host 123.34.56.11 and all machines on the 150.100.23 subnet are allowed access.

    • {deny_from, all | [RegxpHostString]}
      Defines a set of hosts to be denied access to a given directory, for example:

      {deny_from, ["123.34.56.11", "150.100.23"]}

      The host 123.34.56.11 and all machines on the 150.100.23 subnet are not allowed access.

    • {auth_type, plain | dets | mnesia}
      Sets the type of authentication database that is used for the directory. The key difference between the different methods is that dynamic data can be saved @@ -291,7 +291,7 @@ If the password is set to "DummyPassword", the password must be changed before any other API calls. To secure the authenticating data, the password must be changed after the web server is started. Otherwise it is written in clear text -in the configuration file.

    • {require_user, [string()]}
      Defines users to grant access to a given directory using a secret password.

    • {require_group, [string()]}
      Defines users to grant access to a given directory using a secret password.

    Security Properties - Requires mod_security

    {security_directory, {path(), [{property(), term()}]}}

    The properties for the security directories are as follows:

    • {data_file, path()}
      Name of the security data file. The filename can either be absolute or +in the configuration file.

    • {require_user, [string()]}
      Defines users to grant access to a given directory using a secret password.

    • {require_group, [string()]}
      Defines users to grant access to a given directory using a secret password.

    Security Properties - Requires mod_security

    {security_directory, {path(), [{property(), term()}]}}

    The properties for the security directories are as follows:

    • {data_file, path()}
      Name of the security data file. The filename can either be absolute or relative to the server_root. This file is used to store persistent data for module mod_security.

    • {max_retries, integer()}
      Specifies the maximum number of attempts to authenticate a user before the user is blocked out. If a user successfully authenticates while blocked, the @@ -302,10 +302,10 @@ a user authenticates after this time has passed, the previous failed authentications are forgotten. Default is 30.

    • {auth_timeout, integer()}
      Specifies the number of seconds a successful user authentication is remembered. After this time has passed, the authentication is no longer -reported. Default is 30.

    Web server API data types

    The Erlang web server API data types are as follows:

    ModData = #mod{}
    +reported. Default is 30.

  • Web server API data types

    The Erlang web server API data types are as follows:

    ModData = #mod{}
     
    --record(mod, {
    -    data = [],
    +-record(mod, {
    +    data = [],
         socket_type = ip_comm,
         socket,
         config_db,
    @@ -314,10 +314,10 @@
         request_uri,
         http_version,
         request_line,
    -    parsed_header = [],
    +    parsed_header = [],
         entity_body,
         connection
    -}).

    To access the record in your callback-module use:

    -include_lib("inets/include/httpd.hrl").

    The fields of record mod have the following meaning:

    • data - Type [{InteractionKey,InteractionValue}] is used to propagate +}).

      To access the record in your callback-module use:

      -include_lib("inets/include/httpd.hrl").

      The fields of record mod have the following meaning:

      • data - Type [{InteractionKey,InteractionValue}] is used to propagate data between modules. Depicted interaction_data() in function type declarations.

      • socket_type - socket_type() indicates whether it is an IP socket or an ssl socket.

      • socket - The socket, in format ip_comm or ssl, depending on /usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> inets - 9.6.2.2 - urn:uuid:a48ceb05-8c4c-96ac-755f-0e576e13dc66 + urn:uuid:df86d24d-7ca5-e353-db48-975f80d38395 en - 2026-08-21T03:47:50Z + 2042-09-22T17:06:31Z /usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub/OEBPS/http_client.xhtml differs (HTML document, ASCII text, with very long lines (2281)) --- old//usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub/OEBPS/http_client.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub/OEBPS/http_client.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -24,26 +24,26 @@ handle each request, unless a persistent connection can be used with or without pipelining. The client adds a host header and an empty te header if there are no such headers present in the request.

        The client supports IPv6 as long as the underlying mechanisms also do so.

        The following is to be put in the Erlang node application configuration file to -start a profile at application startup:

        [{inets, [{services, [{httpc, PropertyList}]}]}]

        For valid properties, see httpc.

        Getting Started

        Start Inets:

        1> inets:start().
        +start a profile at application startup:

        [{inets, [{services, [{httpc, PropertyList}]}]}]

        For valid properties, see httpc.

        Getting Started

        Start Inets:

        1> inets:start().
         ok

        The following calls use the default client profile. Use the proxy "www-proxy.mycompany.com:8000", except from requests to localhost. This -applies to all the following requests.

        Example:

        2> httpc:set_options([{proxy, {{"www-proxy.mycompany.com", 8000},
        -["localhost"]}}]).
        -ok

        The following is an ordinary synchronous request:

        3> {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} =
        -.. httpc:request(get, {"http://www.erlang.org", []}, [], []).

        With all the default values presented, a get request can also be written as -follows:

        4> {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} =
        -.. httpc:request("http://www.erlang.org").

        The following is a https request and with verification of the host:

        5> {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} =
        -.. httpc:request(get, {"https://www.erlang.org", []}, [{ssl, httpc:ssl_verify_host_options(true)}], []).

        The following is an ordinary asynchronous request:

        6> {ok, RequestId} =
        -.. httpc:request(get, {"http://www.erlang.org", []}, [], [{sync, false}]).

        The result is sent to the calling process as {http, {ReqestId, Result}}.

        In this case, the calling process is the shell, so the following result is -received:

        7> receive {http, {RequestId, Result}} -> ok after 500 -> error end.
        -ok

        This sends a request with a specified connection header:

        8> {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} =
        -.. httpc:request(get, {"http://www.erlang.org", [{"connection", "close"}]},
        -.. [], []).

        This sends an HTTP request over a unix domain socket (experimental):

        9> httpc:set_options([{ipfamily, local}, {unix_socket,"/tmp/unix_socket/consul_http.sock"}]).
        -10> {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} =
        - .. httpc:request(put, {"http:///v1/kv/foo", [], [], "hello"}, [], []).

        Start an HTTP client profile:

        10> {ok, Pid} = inets:start(httpc, [{profile, foo}]).
        -{ok, <0.45.0>}

        The new profile has no proxy settings, so the connection is refused:

        11> httpc:request("http://www.erlang.org", foo).
        -{error, econnrefused}

        Stop the HTTP client profile:

        12> inets:stop(httpc, foo).
        -ok

        Alternative way to stop the HTTP client profile:

        13> inets:stop(httpc, Pid).
        +applies to all the following requests.

        Example:

        2> httpc:set_options([{proxy, {{"www-proxy.mycompany.com", 8000},
        +["localhost"]}}]).
        +ok

        The following is an ordinary synchronous request:

        3> {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} =
        +.. httpc:request(get, {"http://www.erlang.org", []}, [], []).

        With all the default values presented, a get request can also be written as +follows:

        4> {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} =
        +.. httpc:request("http://www.erlang.org").

        The following is a https request and with verification of the host:

        5> {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} =
        +.. httpc:request(get, {"https://www.erlang.org", []}, [{ssl, httpc:ssl_verify_host_options(true)}], []).

        The following is an ordinary asynchronous request:

        6> {ok, RequestId} =
        +.. httpc:request(get, {"http://www.erlang.org", []}, [], [{sync, false}]).

        The result is sent to the calling process as {http, {ReqestId, Result}}.

        In this case, the calling process is the shell, so the following result is +received:

        7> receive {http, {RequestId, Result}} -> ok after 500 -> error end.
        +ok

        This sends a request with a specified connection header:

        8> {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} =
        +.. httpc:request(get, {"http://www.erlang.org", [{"connection", "close"}]},
        +.. [], []).

        This sends an HTTP request over a unix domain socket (experimental):

        9> httpc:set_options([{ipfamily, local}, {unix_socket,"/tmp/unix_socket/consul_http.sock"}]).
        +10> {ok, {{NewVersion, 200, NewReasonPhrase}, NewHeaders, NewBody}} =
        + .. httpc:request(put, {"http:///v1/kv/foo", [], [], "hello"}, [], []).

        Start an HTTP client profile:

        10> {ok, Pid} = inets:start(httpc, [{profile, foo}]).
        +{ok, <0.45.0>}

        The new profile has no proxy settings, so the connection is refused:

        11> httpc:request("http://www.erlang.org", foo).
        +{error, econnrefused}

        Stop the HTTP client profile:

        12> inets:stop(httpc, foo).
        +ok

        Alternative way to stop the HTTP client profile:

        13> inets:stop(httpc, Pid).
         ok
        /usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub/OEBPS/httpc.xhtml differs (HTML document, ASCII text, with very long lines (699)) --- old//usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub/OEBPS/httpc.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub/OEBPS/httpc.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -938,13 +938,13 @@ {http, ReplyInfo}.

      • function/1 - Information is delivered to the receiver through calls to the provided fun Receiver(ReplyInfo).

      • {Module, Function, Args} - Information is delivered to the receiver through calls to the callback function -apply(Module, Function, [ReplyInfo | Args]).

      In all of these cases, ReplyInfo has the following structure:

       {RequestId, saved_to_file}
      - {RequestId, {error, Reason}}
      - {RequestId, Result}
      - {RequestId, stream_start, Headers}
      - {RequestId, stream_start, Headers, HandlerPid}
      - {RequestId, stream, BinBodyPart}
      - {RequestId, stream_end, Headers}

      Default is the pid of the process calling the request function (self/0).

    • ipv6_host_with_brackets - Defines when parsing the Host-Port part of an +apply(Module, Function, [ReplyInfo | Args]).

    In all of these cases, ReplyInfo has the following structure:

     {RequestId, saved_to_file}
    + {RequestId, {error, Reason}}
    + {RequestId, Result}
    + {RequestId, stream_start, Headers}
    + {RequestId, stream_start, Headers, HandlerPid}
    + {RequestId, stream, BinBodyPart}
    + {RequestId, stream_end, Headers}

    Default is the pid of the process calling the request function (self/0).

  • ipv6_host_with_brackets - Defines when parsing the Host-Port part of an URI with an IPv6 address with brackets, if those brackets are to be retained (true) or stripped (false).

    Default is false.

  • /usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub/OEBPS/httpd.xhtml differs (HTML document, ASCII text, with very long lines (2532)) --- old//usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub/OEBPS/httpd.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/inets-9.6.2.2/doc/html/inets.epub/OEBPS/httpd.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -82,36 +82,36 @@ level error under the hierarchical logger domain: [otp, inets, httpd, ServerID, error] The built in logger formatting function produces log entries from the error -reports:

    #{server_name => string()
    +reports:

    #{server_name => string()
       protocol => internal | 'TCP' | 'TLS' | 'HTTP',
       transport => "TCP" | "TLS", %% Present when protocol = 'HTTP'
    -  uri => string(), %% Present when protocol = 'HTTP' and URI is valid
    -  peer => inet:peername(),
    -  host => inet:hostname(),
    -  reason => term()
    -}

    An example of a log entry with only default settings of logger

    =ERROR REPORT==== 9-Oct-2019::09:33:27.350235 ===
    +  uri => string(), %% Present when protocol = 'HTTP' and URI is valid
    +  peer => inet:peername(),
    +  host => inet:hostname(),
    +  reason => term()
    +}

    An example of a log entry with only default settings of logger

    =ERROR REPORT==== 9-Oct-2019::09:33:27.350235 ===
        Server: My Server
      Protocol: HTTP
     Transport: TLS
           URI: /not_there
          Host: 127.0.1.1:80
          Peer: 127.0.0.1:45253
    -   Reason: [{statuscode,404},{description,"Object Not Found"}]

    Using this option makes mod_log and mod_disk_log error logs redundant.

    Add the filter

    {fun logger_filters:domain/2,
    -    {log,equal,[otp,inets, httpd, ServerID, error]}

    to appropriate logger handler to handle the events. For example to write the + Reason: [{statuscode,404},{description,"Object Not Found"}]

    Using this option makes mod_log and mod_disk_log error logs redundant.

    Add the filter

    {fun logger_filters:domain/2,
    +    {log,equal,[otp,inets, httpd, ServerID, error]}

    to appropriate logger handler to handle the events. For example to write the error log from an httpd server with a ServerID of my_server to a file -you can use the following sys.config:

    [{kernel,
    - [{logger,
    -  [{handler, http_error_test, logger_std_h,
    -    #{config => #{ file => "log/http_error.log" },
    -      filters => [{inets_httpd, {fun logger_filters:domain/2,
    -                                 {log, equal,
    -                                  [otp, inets, httpd, my_server, error]
    -                                 }}}],
    -      filter_default => stop }}]}]}].

    or if you want to add it to the default logger via an API:

    logger:add_handler_filter(default,
    +you can use the following sys.config:

    [{kernel,
    + [{logger,
    +  [{handler, http_error_test, logger_std_h,
    +    #{config => #{ file => "log/http_error.log" },
    +      filters => [{inets_httpd, {fun logger_filters:domain/2,
    +                                 {log, equal,
    +                                  [otp, inets, httpd, my_server, error]
    +                                 }}}],
    +      filter_default => stop }}]}]}].

    or if you want to add it to the default logger via an API:

    logger:add_handler_filter(default,
                               inets_httpd,
    -                          {fun logger_filters:domain/2,
    -                           {log, equal,
    -                            [otp, inets, httpd, my_server, error]}}).
  • {log_format, common | combined}
    Defines if access logs are to be written according to the common log format + {fun logger_filters:domain/2, + {log, equal, + [otp, inets, httpd, my_server, error]}}).

  • {log_format, common | combined}
    Defines if access logs are to be written according to the common log format or the extended common log format. The common format is one line looking like this: remotehost rfc931 authuser [date] "request" status bytes.

    Here:

    • remotehost - Remote.

    • rfc931 - The remote username of the client (RFC 931).

    • authuser - The username used for authentication.

    • [date] - Date and time of the request @@ -121,18 +121,18 @@ remotehost rfc931 authuser [date] "request" status bytes "referer" "user_agent"

      In addition to the earlier:

      • "referer" - The URL the client was on before requesting the URL (if it could not be determined, a minus sign is placed in this field).

      • "user_agent" - The software the client claims to be using (if it could not be determined, a minus sign is placed in this field).

      This affects the access logs written by mod_log and mod_disk_log.

    • {error_log_format, pretty | compact}
      Default is pretty. If the error log is meant to be read directly by a human, -pretty is the best option.

      pretty has a format corresponding to:

      io:format("[~s] ~s, reason: ~n ~p ~n~n", [Date, Msg, Reason]).

      compact has a format corresponding to:

      io:format("[~s] ~s, reason: ~w ~n", [Date, Msg, Reason]).

      This affects the error logs written by mod_log and mod_disk_log.

    URL Aliasing Properties - Requires mod_alias

    • {alias, {Alias, RealName}}
      Alias = string() and RealName = string(). alias allows documents to be +pretty is the best option.

      pretty has a format corresponding to:

      io:format("[~s] ~s, reason: ~n ~p ~n~n", [Date, Msg, Reason]).

      compact has a format corresponding to:

      io:format("[~s] ~s, reason: ~w ~n", [Date, Msg, Reason]).

      This affects the error logs written by mod_log and mod_disk_log.

    URL Aliasing Properties - Requires mod_alias

    • {alias, {Alias, RealName}}
      Alias = string() and RealName = string(). alias allows documents to be stored in the local file system instead of the document_root location. URLs with a path beginning with url-path is mapped to local files beginning with -directory-filename, for example:

      {alias, {"/image", "/ftp/pub/image"}}

      Access to http://your.server.org/image/foo.gif would refer to the file +directory-filename, for example:

      {alias, {"/image", "/ftp/pub/image"}}

      Access to http://your.server.org/image/foo.gif would refer to the file /ftp/pub/image/foo.gif.

    • {re_write, {Re, Replacement}}
      Re = string() and Replacement = string(). re_write allows documents to be stored in the local file system instead of the document_root location. URLs are rewritten by re:replace/3 to produce a path in the local -file-system, for example:

      {re_write, {"^/[~]([^/]+)(.*)$", "/home/\\1/public\\2"}}

      Access to http://your.server.org/~bob/foo.gif would refer to the file +file-system, for example:

      {re_write, {"^/[~]([^/]+)(.*)$", "/home/\\1/public\\2"}}

      Access to http://your.server.org/~bob/foo.gif would refer to the file /home/bob/public/foo.gif.

    • {directory_index, [string()]}
      directory_index specifies a list of resources to look for if a client requests a directory using a / at the end of the directory name. file depicts the name of a file in the directory. Several files can be given, in -which case the server returns the first it finds, for example:

      {directory_index, ["index.html", "welcome.html"]}

      Access to http://your.server.org/docs/ would return +which case the server returns the first it finds, for example:

      {directory_index, ["index.html", "welcome.html"]}

      Access to http://your.server.org/docs/ would return http://your.server.org/docs/index.html or http://your.server.org/docs/welcome.html if index.html does not exist.

    CGI Properties - Requires mod_cgi

    • {script_alias, {Alias, RealName}}
      Alias = string() and RealName = string(). Have the same behavior as property alias, except that they also mark the target directory as @@ -157,9 +157,9 @@ method. The method is either GET or POST, as defined in RFC 1945. It propagates the URL and file path of the requested document using the standard CGI PATH_INFO and -PATH_TRANSLATED environment variables.

      Example:

      {script, {"PUT", "/cgi-bin/put"}}

    ESI Properties - Requires mod_esi

    • {erl_script_alias, {URLPath, [AllowedModule]}}
      URLPath = string() and AllowedModule = atom(). erl_script_alias marks +PATH_TRANSLATED environment variables.

      Example:

      {script, {"PUT", "/cgi-bin/put"}}

    ESI Properties - Requires mod_esi

    • {erl_script_alias, {URLPath, [AllowedModule]}}
      URLPath = string() and AllowedModule = atom(). erl_script_alias marks all URLs matching url-path as erl scheme scripts. A matching URL is mapped -into a specific module and function, for example:

      {erl_script_alias, {"/cgi-bin/example", [httpd_example]}}

      A request to http://your.server.org/cgi-bin/example/httpd_example:yahoo would +into a specific module and function, for example:

      {erl_script_alias, {"/cgi-bin/example", [httpd_example]}}

      A request to http://your.server.org/cgi-bin/example/httpd_example:yahoo would refer to httpd_example:yahoo/3 or, if that does not exist, httpd_example:yahoo/2 and http://your.server.org/cgi-bin/example/other:yahoo would not be allowed to execute.

    • {erl_script_nocache, boolean()}
      If erl_script_nocache is set to true, the server adds HTTP header fields @@ -191,7 +191,7 @@ relative to the server_root.

    • {transfer_disk_log_size, {MaxBytes, MaxFiles}}
      MaxBytes = integer() and MaxFiles = integer(). Defines the properties of the disk_log access log file. This file is of type wrap log and max bytes is written to each file and max files is used before the first file is -truncated and reused.

    Authentication Properties - Requires mod_auth

    {directory, {path(), [{property(), term()}]}}

    The properties for directories are as follows:

    • {allow_from, all | [RegxpHostString]}
      Defines a set of hosts to be granted access to a given directory, for example:

      {allow_from, ["123.34.56.11", "150.100.23"]}

      The host 123.34.56.11 and all machines on the 150.100.23 subnet are +truncated and reused.

    Authentication Properties - Requires mod_auth

    {directory, {path(), [{property(), term()}]}}

    The properties for directories are as follows:

    • {allow_from, all | [RegxpHostString]}
      Defines a set of hosts to be granted access to a given directory, for example:

      {allow_from, ["123.34.56.11", "150.100.23"]}

      The host 123.34.56.11 and all machines on the 150.100.23 subnet are allowed access.

    • {deny_from, all | [RegxpHostString]}
      Defines a set of hosts to be denied access to a given directory, for example:

      {deny_from, ["123.34.56.11", "150.100.23"]}

      The host 123.34.56.11 and all machines on the 150.100.23 subnet are not allowed access.

    • {auth_type, plain | dets | mnesia}
      Sets the type of authentication database that is used for the directory. The key difference between the different methods is that dynamic data can be saved @@ -220,7 +220,7 @@ If the password is set to "DummyPassword", the password must be changed before any other API calls. To secure the authenticating data, the password must be changed after the web server is started. Otherwise it is written in clear text -in the configuration file.

    • {require_user, [string()]}
      Defines users to grant access to a given directory using a secret password.

    • {require_group, [string()]}
      Defines users to grant access to a given directory using a secret password.

    Security Properties - Requires mod_security

    {security_directory, {path(), [{property(), term()}]}}

    The properties for the security directories are as follows:

    • {data_file, path()}
      Name of the security data file. The filename can either be absolute or +in the configuration file.

    • {require_user, [string()]}
      Defines users to grant access to a given directory using a secret password.

    • {require_group, [string()]}
      Defines users to grant access to a given directory using a secret password.

    Security Properties - Requires mod_security

    {security_directory, {path(), [{property(), term()}]}}

    The properties for the security directories are as follows:

    • {data_file, path()}
      Name of the security data file. The filename can either be absolute or relative to the server_root. This file is used to store persistent data for module mod_security.

    • {max_retries, integer()}
      Specifies the maximum number of attempts to authenticate a user before the user is blocked out. If a user successfully authenticates while blocked, the @@ -231,10 +231,10 @@ a user authenticates after this time has passed, the previous failed authentications are forgotten. Default is 30.

    • {auth_timeout, integer()}
      Specifies the number of seconds a successful user authentication is remembered. After this time has passed, the authentication is no longer -reported. Default is 30.

    Web server API data types

    The Erlang web server API data types are as follows:

    ModData = #mod{}
    +reported. Default is 30.

  • Web server API data types

    The Erlang web server API data types are as follows:

    ModData = #mod{}
     
    --record(mod, {
    -    data = [],
    +-record(mod, {
    +    data = [],
         socket_type = ip_comm,
         socket,
         config_db,
    @@ -243,10 +243,10 @@
         request_uri,
         http_version,
         request_line,
    -    parsed_header = [],
    +    parsed_header = [],
         entity_body,
         connection
    -}).

    To access the record in your callback-module use:

    -include_lib("inets/include/httpd.hrl").

    The fields of record mod have the following meaning:

  • {sctp_events, #href_anchor"" id="option-sctp_events">

    #sctp_event_subscribe{
    +Sockets API Extensions for SCTP.

  • {sctp_events, #href_anchor"" id="option-sctp_events">

    #sctp_event_subscribe{
             data_io_event          = true | false,
             association_event      = true | false,
             address_event          = true | false,
    @@ -247,42 +247,42 @@
             shutdown_event         = true | false,
             partial_delivery_event = true | false,
             adaptation_layer_event = true | false
    -}

    This option determines which SCTP Events that are to be +}

    This option determines which SCTP Events that are to be received (through recv/*) along with the data. The only exception is data_io_event, which enables or disables receiving of #sctp_sndrcvinfo{} ancillary data, not events. By default, all flags except adaptation_layer_event are enabled, although sctp_data_io_event and association_event are used by the driver -itself and not exported to the user level.

  • {sctp_delayed_ack_time, #sctp_assoc_value{}}

    #sctp_assoc_value{
    -      assoc_id    = assoc_id(),
    -      assoc_value = integer()
    -}

    Rarely used. Determines the ACK time (specified by assoc_value, in +itself and not exported to the user level.

  • {sctp_delayed_ack_time, #sctp_assoc_value{}}

    #sctp_assoc_value{
    +      assoc_id    = assoc_id(),
    +      assoc_value = integer()
    +}

    Rarely used. Determines the ACK time (specified by assoc_value, in milliseconds) for the specified association or the whole endpoint if -assoc_value = 0 (default).

  • {sctp_status, #sctp_status{}}

    #sctp_status{
    -      assoc_id            = assoc_id(),
    -      state               = atom(),
    -      rwnd                = integer(),
    -      unackdata           = integer(),
    -      penddata            = integer(),
    -      instrms             = integer(),
    -      outstrms            = integer(),
    -      fragmentation_point = integer(),
    -      primary             = #sctp_paddrinfo{}
    -}

    This option is read-only. It determines the status of the SCTP association +assoc_value = 0 (default).

  • {sctp_status, #sctp_status{}}

    #sctp_status{
    +      assoc_id            = assoc_id(),
    +      state               = atom(),
    +      rwnd                = integer(),
    +      unackdata           = integer(),
    +      penddata            = integer(),
    +      instrms             = integer(),
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/gen_tcp.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (898))
    --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/gen_tcp.html	2026-08-21 04:00:23.751322935 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/gen_tcp.html	2026-08-21 04:00:23.752322941 +0000
    @@ -95,27 +95,27 @@
         

    Interface to TCP/IP sockets.

    This module provides functions for communicating over TCP/IP protocol sockets.

    The following code fragment is a simple example of a client connecting to a -server at port 5678, transferring a binary, and closing the connection:

    client() ->
    +server at port 5678, transferring a binary, and closing the connection:

    client() ->
         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"),
    -    ok = gen_tcp:close(Sock).

    At the other end, a server is listening on port 5678, accepts the connection, -and receives the binary:

    server() ->
    -    {ok, LSock} = gen_tcp:listen(5678, [binary, {packet, 0},
    -                                        {active, false}]),
    -    {ok, Sock} = gen_tcp:accept(LSock),
    -    {ok, Bin} = do_recv(Sock, []),
    -    ok = gen_tcp:close(Sock),
    -    ok = gen_tcp:close(LSock),
    +    {ok, Sock} = gen_tcp:connect(SomeHostInNet, 5678,
    +                                 [binary, {packet, 0}]),
    +    ok = gen_tcp:send(Sock, "Some Data"),
    +    ok = gen_tcp:close(Sock).

    At the other end, a server is listening on port 5678, accepts the connection, +and receives the binary:

    server() ->
    +    {ok, LSock} = gen_tcp:listen(5678, [binary, {packet, 0},
    +                                        {active, false}]),
    +    {ok, Sock} = gen_tcp:accept(LSock),
    +    {ok, Bin} = do_recv(Sock, []),
    +    ok = gen_tcp:close(Sock),
    +    ok = gen_tcp:close(LSock),
         Bin.
     
    -do_recv(Sock, Bs) ->
    -    case gen_tcp:recv(Sock, 0) of
    -        {ok, B} ->
    -            do_recv(Sock, [Bs, B]);
    -        {error, closed} ->
    -            {ok, list_to_binary(Bs)}
    +do_recv(Sock, Bs) ->
    +    case gen_tcp:recv(Sock, 0) of
    +        {ok, B} ->
    +            do_recv(Sock, [Bs, B]);
    +        {error, closed} ->
    +            {ok, list_to_binary(Bs)}
         end.

    For more examples, see section Examples.

    Note

    Functions that create sockets can take an optional option; {inet_backend, Backend} that, if specified, has to be the first option. This selects the implementation backend towards the platform's socket API.

    This is a temporary option that will be ignored in a future release.

    The default is Backend = inet that selects the traditional inet_drv.c @@ -148,48 +148,48 @@ a single listening socket. Function start/2 takes the number of worker processes and the port number on which to listen for incoming connections. If LPort is specified as 0, an ephemeral port number is used, which is why the -start function returns the actual port number allocated:

    start(Num,LPort) ->
    -    case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of
    -        {ok, ListenSock} ->
    -            start_servers(Num,ListenSock),
    -            {ok, Port} = inet:port(ListenSock),
    +start function returns the actual port number allocated:

    start(Num,LPort) ->
    +    case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of
    +        {ok, ListenSock} ->
    +            start_servers(Num,ListenSock),
    +            {ok, Port} = inet:port(ListenSock),
                 Port;
    -        {error,Reason} ->
    -            {error,Reason}
    +        {error,Reason} ->
    +            {error,Reason}
         end.
     
    -start_servers(0,_) ->
    +start_servers(0,_) ->
         ok;
    -start_servers(Num,LS) ->
    -    spawn(?MODULE,server,[LS]),
    -    start_servers(Num-1,LS).
    +start_servers(Num,LS) ->
    +    spawn(?MODULE,server,[LS]),
    +    start_servers(Num-1,LS).
     
    -server(LS) ->
    -    case gen_tcp:accept(LS) of
    -        {ok,S} ->
    -            loop(S),
    -            server(LS);
    +server(LS) ->
    +    case gen_tcp:accept(LS) of
    +        {ok,S} ->
    +            loop(S),
    +            server(LS);
             Other ->
    -            io:format("accept returned ~w - goodbye!~n",[Other]),
    +            io:format("accept returned ~w - goodbye!~n",[Other]),
                 ok
         end.
     
    -loop(S) ->
    -    inet:setopts(S,[{active,once}]),
    +loop(S) ->
    +    inet:setopts(S,[{active,once}]),
         receive
    -        {tcp,S,Data} ->
    -            Answer = process(Data), % Not implemented in this example
    -            gen_tcp:send(S,Answer),
    -            loop(S);
    -        {tcp_closed,S} ->
    -            io:format("Socket ~w closed [~w]~n",[S,self()]),
    +        {tcp,S,Data} ->
    +            Answer = process(Data), % Not implemented in this example
    +            gen_tcp:send(S,Answer),
    +            loop(S);
    +        {tcp_closed,S} ->
    +            io:format("Socket ~w closed [~w]~n",[S,self()]),
                 ok
    -    end.

    Example of a simple client:

    client(PortNo,Message) ->
    -    {ok,Sock} = gen_tcp:connect("localhost",PortNo,[{active,false},
    -                                                    {packet,2}]),
    -    gen_tcp:send(Sock,Message),
    -    A = gen_tcp:recv(Sock,0),
    -    gen_tcp:close(Sock),
    +    end.

    Example of a simple client:

    client(PortNo,Message) ->
    +    {ok,Sock} = gen_tcp:connect("localhost",PortNo,[{active,false},
    +                                                    {packet,2}]),
    +    gen_tcp:send(Sock,Message),
    +    A = gen_tcp:recv(Sock,0),
    +    gen_tcp:close(Sock),
         A.

    The send call does not accept a time-out option because time-outs on send is handled through socket option send_timeout. The behavior of a send operation with no receiver is mainly defined by the underlying TCP stack and the network @@ -199,32 +199,32 @@ does not get any acknowledge for each message it sends, but has to rely on the send time-out option to detect that the other end is unresponsive. Option send_timeout can be used when connecting:

    ...
    -{ok,Sock} = gen_tcp:connect(HostAddress, Port,
    -                            [{active,false},
    -                             {send_timeout, 5000},
    -                             {packet,2}]),
    -                loop(Sock), % See below
    -...

    In the loop where requests are handled, send time-outs can now be detected:

    loop(Sock) ->
    +{ok,Sock} = gen_tcp:connect(HostAddress, Port,
    +                            [{active,false},
    +                             {send_timeout, 5000},
    +                             {packet,2}]),
    +                loop(Sock), % See below
    +...

    In the loop where requests are handled, send time-outs can now be detected:

    loop(Sock) ->
         receive
    -        {Client, send_data, Binary} ->
    -            case gen_tcp:send(Sock,[Binary]) of
    -                {error, timeout} ->
    -                    io:format("Send timeout, closing!~n",
    -                              []),
    -                    handle_send_timeout(), % Not implemented here
    -                    Client ! {self(),{error_sending, timeout}},
    +        {Client, send_data, Binary} ->
    +            case gen_tcp:send(Sock,[Binary]) of
    +                {error, timeout} ->
    +                    io:format("Send timeout, closing!~n",
    +                              []),
    +                    handle_send_timeout(), % Not implemented here
    +                    Client ! {self(),{error_sending, timeout}},
                         %% Usually, it's a good idea to give up in case of a
                         %% send timeout, as you never know how much actually
                         %% reached the server, maybe only a packet header?!
    -                    gen_tcp:close(Sock);
    -                {error, OtherSendError} ->
    -                    io:format("Some other error on socket (~p), closing",
    -                              [OtherSendError]),
    -                    Client ! {self(),{error_sending, OtherSendError}},
    -                    gen_tcp:close(Sock);
    +                    gen_tcp:close(Sock);
    +                {error, OtherSendError} ->
    +                    io:format("Some other error on socket (~p), closing",
    +                              [OtherSendError]),
    +                    Client ! {self(),{error_sending, OtherSendError}},
    +                    gen_tcp:close(Sock);
                     ok ->
    -                    Client ! {self(), data_sent},
    -                    loop(Sock)
    +                    Client ! {self(), data_sent},
    +                    loop(Sock)
                 end
         end.

    Usually it suffices to detect time-outs on receive, as most protocols include some sort of acknowledgment from the server, but if the protocol is strictly one /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/gen_udp.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (770)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/gen_udp.html 2026-08-21 04:00:23.779323117 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/gen_udp.html 2026-08-21 04:00:23.778323110 +0000 @@ -919,8 +919,8 @@ Leaves a multicast group.

  • option/0 - See inet:setopts/2.

  • UDP packets are sent with this socket using send(Socket, ...). When UDP packets arrive to the Socket's UDP port, and the socket is in an active mode, the packets are delivered as messages to the -controlling process (socket owner):

    {udp, Socket, PeerIP, PeerPort, Packet} % Without ancillary data
    -{udp, Socket, PeerIP, PeerPort, AncData, Packet} % With ancillary data

    PeerIP and PeerPort are the address from which Packet was sent. +controlling process (socket owner):

    {udp, Socket, PeerIP, PeerPort, Packet} % Without ancillary data
    +{udp, Socket, PeerIP, PeerPort, AncData, Packet} % With ancillary data

    PeerIP and PeerPort are the address from which Packet was sent. Packet is a list of bytes ([byte/0] if option list is active and a binary/0 if option binaryis active (they are mutually exclusive).

    The message contains an AncData field only if any of the socket @@ -928,8 +928,8 @@ recvtclass or recvttl are active.

    When a socket in {active, N} mode (see inet:setopts/2 for details), transitions to passive ({active, false}) mode (N counts down to 0), -the controlling process is notified by a message on this form:

    {udp_passive, Socket}

    If the OS protocol stack reports an error for the socket, the following -message is sent to the controlling process:

    {udp_error, Socket, Reason}

    Reason is mostly a POSIX Error Code.

    If the socket is in passive mode (not in an active mode), received data +the controlling process is notified by a message on this form:

    {udp_passive, Socket}

    If the OS protocol stack reports an error for the socket, the following +message is sent to the controlling process:

    {udp_error, Socket, Reason}

    Reason is mostly a POSIX Error Code.

    If the socket is in passive mode (not in an active mode), received data can be retrieved with therecv/2,3](recv/2) calls. Note that incoming UDP packets that are longer than the receive buffer option specifies can be truncated without warning.

    The default value for the receive buffer option is {recbuf, 9216}.

    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/global_group.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/global_group.html 2026-08-21 04:00:23.801323260 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/global_group.html 2026-08-21 04:00:23.801323260 +0000 @@ -97,7 +97,7 @@ groups. Each global group has its own global namespace, see global.

    The main advantage of dividing systems into global groups is that the background load decreases while the number of nodes to be updated is reduced when manipulating globally registered names.

    The Kernel configuration parameter global_groups -defines the global groups:

    {global_groups, [GroupTuple :: group_tuple()]}

    For the processes and nodes to run smoothly using the global group +defines the global groups:

    {global_groups, [GroupTuple :: group_tuple()]}

    For the processes and nodes to run smoothly using the global group functionality, the following criteria must be met:

    completion_sendv(Sock, IOV) ->
    -    case socket:sendv(Sock, IOV, nowait) of
    +socket:sendv(Sock, IOV, infinity).

    completion_sendv(Sock, IOV) ->
    +    case socket:sendv(Sock, IOV, nowait) of
             ok -> % Complete success - We are done
                 ok;
    -        {completion, {CompletionInfo, RestIOV0}} ->
    +        {completion, {CompletionInfo, RestIOV0}} ->
                 %% Some of IOV was sent, but the rest, RestIOV0, was scheduled
    -            case completion_sendv_await_result(Sock,
    -                                               CompletionInfo, RestIOV0) of
    +            case completion_sendv_await_result(Sock,
    +                                               CompletionInfo, RestIOV0) of
                     ok -> % We done
                         ok;
    -                {ok, RestIOV} ->
    -                    completion_sendv(Sock, RestIOV);
    -                {error, Reason} ->
    -                    {error, {Reason, RestIOV0}}
    +                {ok, RestIOV} ->
    +                    completion_sendv(Sock, RestIOV);
    +                {error, Reason} ->
    +                    {error, {Reason, RestIOV0}}
                 end;
    -        {completion, CompletionInfo} ->
    +        {completion, CompletionInfo} ->
                 %% Nothing was sent, IOV was scheduled
    -            case completion_sendv_await_result(Sock,
    -                                               CompletionInfo, IOV) of
    +            case completion_sendv_await_result(Sock,
    +                                               CompletionInfo, IOV) of
                     ok -> % We done
                         ok;
    -                {ok, RestIOV} ->
    -                    completion_sendv(Sock, RestIOV);
    -                {error, _} = ERROR ->
    +                {ok, RestIOV} ->
    +                    completion_sendv(Sock, RestIOV);
    +                {error, _} = ERROR ->
                         ERROR
                 end;
    -        {error, {_Reason, _RestIOV}} = ERROR ->
    +        {error, {_Reason, _RestIOV}} = ERROR ->
                 %% Some part of the I/O vector was sent before an error occured
                 ERROR;
    -        {error, _} = ERROR ->
    +        {error, _} = ERROR ->
                 %% Note that 
                 ERROR
         end.
     
    -completion_sendv_await_result(Sock,
    -                              {completion_info, _, Handle},
    -                              IOV) ->
    +completion_sendv_await_result(Sock,
    +                              {completion_info, _, Handle},
    +                              IOV) ->
       receive
    -      {'$socket', Sock, abort, {Handle, Reason}} ->
    -          ?P("unexpected abort: "
    -             "~n   Reason: ~p", [Reason]),
    -          {error, {abort, Reason}};
    +      {'$socket', Sock, abort, {Handle, Reason}} ->
    +          ?P("unexpected abort: "
    +             "~n   Reason: ~p", [Reason]),
    +          {error, {abort, Reason}};
     
    -      {'$socket', Sock, completion, {Handle, {ok, Written}}} ->
    +      {'$socket', Sock, completion, {Handle, {ok, Written}}} ->
               %% Partial send; calculate rest I/O vector
    -          case socket:rest_iov(Written, IOV) of
    -              [] -> % We are done
    +          case socket:rest_iov(Written, IOV) of
    +              [] -> % We are done
                       ok;
                   RestIOV ->
    -                  {ok, RestIOV}
    +                  {ok, RestIOV}
               end;
     
    -      {'$socket', Sock, completion, {Handle, CompletionStatus}} ->
    +      {'$socket', Sock, completion, {Handle, CompletionStatus}} ->
               CompletionStatus
     
       end.

    Completion asynchronous recv

    This is a simple example function that illustrates how to use @@ -117,95 +117,95 @@ Observe that this is not an illustration how to write a asynchronous read function. Its just an example of what kind of messages and results that can be expected. The example below basically (re-) implements: -socket:recv(Sock, Sz).

    completion_recv(Sock, Sz) when (Sz > 0) ->
    -    completion_recv(Sock, Sz, []).
    +socket:recv(Sock, Sz).

    completion_recv(Sock, Sz) when (Sz > 0) ->
    +    completion_recv(Sock, Sz, []).
     
    -completion_recv(_Sock, 0, [Bin] = _Acc) ->
    -    {ok, Bin};
    -completion_recv(_Sock, 0, Acc) ->
    -    {ok, erlang:iolist_to_binary(lists:reverse(Acc))};
    -completion_recv(Sock, Sz, Acc) ->
    -    case socket:recv(Sock, Sz, nowait) of
    -        {ok, Bin} when (byte_size(Bin) =:= Sz) ->
    -            completion_recv(Sock, 0, [Bin|Acc]);
    -        {ok, Bin} ->
    -            completion_recv(Sock, Sz-byte_size(Bin), [Bin|Acc]);
    -
    -	{completion, CompletionInfo} ->
    -            case completion_recv_await_result(Sock, CompletionInfo) of
    -                {ok, Bin} ->
    -                    completion_recv(Sock, Sz-byte_size(Bin), [Bin|Acc]);
    -                {error, {_Reason, _Data}} = ERROR ->
    +completion_recv(_Sock, 0, [Bin] = _Acc) ->
    +    {ok, Bin};
    +completion_recv(_Sock, 0, Acc) ->
    +    {ok, erlang:iolist_to_binary(lists:reverse(Acc))};
    +completion_recv(Sock, Sz, Acc) ->
    +    case socket:recv(Sock, Sz, nowait) of
    +        {ok, Bin} when (byte_size(Bin) =:= Sz) ->
    +            completion_recv(Sock, 0, [Bin|Acc]);
    +        {ok, Bin} ->
    +            completion_recv(Sock, Sz-byte_size(Bin), [Bin|Acc]);
    +
    +	{completion, CompletionInfo} ->
    +            case completion_recv_await_result(Sock, CompletionInfo) of
    +                {ok, Bin} ->
    +                    completion_recv(Sock, Sz-byte_size(Bin), [Bin|Acc]);
    +                {error, {_Reason, _Data}} = ERROR ->
                         ERROR;
    -                {error, _Reason} = ERROR ->
    +                {error, _Reason} = ERROR ->
                         ERROR
     	    end;
     
    -	{error, {_Reason, _Data}} = ERROR ->
    +	{error, {_Reason, _Data}} = ERROR ->
     	    ERROR;
    -	{error, _Reason} = ERROR ->
    +	{error, _Reason} = ERROR ->
     	    ERROR
     
         end.
     
    -completion_recv_await_result(Sock,
    -                             {completion_info, _, Handle}) ->
    +completion_recv_await_result(Sock,
    +                             {completion_info, _, Handle}) ->
         receive
    -	{'$socket', Sock, abort, {Handle, Reason}} ->
    -	    {error, {abort, Reason}};
    +	{'$socket', Sock, abort, {Handle, Reason}} ->
    +	    {error, {abort, Reason}};
     
    -	{'$socket', Sock, completion, {Handle, {ok, _Bin} = OK}} ->
    +	{'$socket', Sock, completion, {Handle, {ok, _Bin} = OK}} ->
                 %% We "should" be done
     	    OK;
    -	{'$socket', Sock, completion, {Handle, {more, Bin}}} ->
    +	{'$socket', Sock, completion, {Handle, {more, Bin}}} ->
                 %% There is more to read
    -	    {ok, Bin};
    +	    {ok, Bin};
     
    -	{'$socket', Sock, completion, {Handle, CompletionStatus}} ->
    +	{'$socket', Sock, completion, {Handle, CompletionStatus}} ->
     	    CompletionStatus
     
         end.

    Echo server (and client)

    This example is intended to show how to create a simple (echo) server -(and client).

    -module(example).
    +(and client).

    -module(example).
     
    --export([client/2, client/3]).
    --export([server/0, server/1, server/2]).
    +-export([client/2, client/3]).
    +-export([server/0, server/1, server/2]).
     
     
     %% ======================================================================
     
     %% === Client ===
     
    -client(#{family := Family} = ServerSockAddr, Msg)
    -  when is_list(Msg) orelse is_binary(Msg) ->
    -    {ok, Sock} = socket:open(Family, stream, default),
    -    ok         = maybe_bind(Sock, Family),
    -    ok         = socket:connect(Sock, ServerSockAddr),
    -    client_exchange(Sock, Msg);
    +client(#{family := Family} = ServerSockAddr, Msg)
    +  when is_list(Msg) orelse is_binary(Msg) ->
    +    {ok, Sock} = socket:open(Family, stream, default),
    +    ok         = maybe_bind(Sock, Family),
    +    ok         = socket:connect(Sock, ServerSockAddr),
    +    client_exchange(Sock, Msg);
     
    -client(ServerPort, Msg)
    -  when is_integer(ServerPort) andalso (ServerPort > 0) ->
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/socket.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (961))
    --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/socket.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/socket.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -82,8 +82,8 @@
     to only scan the messages that arrive after the reference/0
     is created.  If the message queue is large this is a big optimization.

    It is not possible to have more than one operation in progress with the same reference/0.

    Repeating an Operation on a select Systems

    Onselect systems, if a call would be repeated before the select -message has been received it replaces the operation in progress:

        {select, {select_info, Handle}} = socket:accept(LSock, nowait),
    -    {ok, Socket} = socket:accept(LSock, 1000),
    +message has been received it replaces the operation in progress:

        {select, {select_info, Handle}} = socket:accept(LSock, nowait),
    +    {ok, Socket} = socket:accept(LSock, 1000),
         :

    Above, Handle is no longer valid once the second accept/2, call has been made (the first call is automatically canceled). After the second accept/2 call returns, the accept operation @@ -110,28 +110,28 @@ (select handle) API features could be considered no longer experimental.

  • In OTP 27.0, the Windows flavored (completion handle) -API features could be considered no longer experimental.
  • Examples

    client(SAddr, SPort) ->
    -   {ok, Sock} = socket:open(inet, stream, tcp),
    -   ok = socket:connect(Sock, #{family => inet,
    +API features could be considered no longer experimental.

    Examples

    client(SAddr, SPort) ->
    +   {ok, Sock} = socket:open(inet, stream, tcp),
    +   ok = socket:connect(Sock, #{family => inet,
                                    addr   => SAddr,
    -                               port   => SPort}),
    -   Msg = <<"hello">>,
    -   ok = socket:send(Sock, Msg),
    -   ok = socket:shutdown(Sock, write),
    -   {ok, Msg} = socket:recv(Sock),
    -   ok = socket:close(Sock).
    -
    -server(Addr, Port) ->
    -   {ok, LSock} = socket:open(inet, stream, tcp),
    -   ok = socket:bind(LSock, #{family => inet,
    +                               port   => SPort}),
    +   Msg = <<"hello">>,
    +   ok = socket:send(Sock, Msg),
    +   ok = socket:shutdown(Sock, write),
    +   {ok, Msg} = socket:recv(Sock),
    +   ok = socket:close(Sock).
    +
    +server(Addr, Port) ->
    +   {ok, LSock} = socket:open(inet, stream, tcp),
    +   ok = socket:bind(LSock, #{family => inet,
                                  port   => Port,
    -                             addr   => Addr}),
    -   ok = socket:listen(LSock),
    -   {ok, Sock} = socket:accept(LSock),
    -   {ok, Msg} = socket:recv(Sock),
    -   ok = socket:send(Sock, Msg),
    -   ok = socket:close(Sock),
    -   ok = socket:close(LSock).
    +
    addr => Addr}), + ok = socket:listen(LSock), + {ok, Sock} = socket:accept(LSock), + {ok, Msg} = socket:recv(Sock), + ok = socket:send(Sock, Msg), + ok = socket:close(Sock), + ok = socket:close(LSock).
    @@ -4762,7 +4762,7 @@ (since OTP 26.1).

    Result; a boolean/0.

  • tcp_info - Get miscellaneous TCP related information for a connected socket (since OTP 26.1).

    Result; a map/0 with information items as key-value pairs.

  • Note

    Not all requests are supported by all platforms. To see if a ioctl request is supported on the current platform:

          Request = nread,
    -      true = socket:is_supported(ioctl_requests, Request),
    +      true = socket:is_supported(ioctl_requests, Request),
           :
    @@ -4926,7 +4926,7 @@

    Check if a socket feature is supported.

    Returns true if supports/0 has a {Key1, true} tuple or a {Key1, list()} tuple in its returned list, -otherwise false (also for unknown keys).

    Example:

    true = socket:is_supported(local),
    +otherwise false (also for unknown keys).

    Example:

    true = socket:is_supported(local),
    @@ -4957,7 +4957,7 @@

    Check if a socket feature is supported.

    Returns true if supports(Key1) has a {Key2, true} tuple -in its returned list, otherwise false (also for unknown keys).

    Example:

    true = socket:is_supported(msg_flags, errqueue),
    +in its returned list, otherwise false (also for unknown keys).

    Example:

    true = socket:is_supported(msg_flags, errqueue),
    @@ -5054,7 +5054,7 @@

    Start a socket monitor.

    If the Socket doesn't exist or when later the monitor is triggered, a 'DOWN' message is sent to the process that called monitor/1 -with the following pattern:

    	    {'DOWN', MonitorRef, socket, Socket, Info}

    Info is the termination reason of the socket or nosock if +with the following pattern:

    	    {'DOWN', MonitorRef, socket, Socket, Info}

    Info is the termination reason of the socket or nosock if Socket did not exist when the monitor was started.

    Making several calls to socket:monitor/1 for the same Socket is not an error; each call creates an independent monitor instance.

    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/trace.xhtml differs (HTML document, ASCII text, with very long lines (4890)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/trace.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/trace.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -34,23 +34,23 @@ messages. Several sessions can exist at the same time without interfering with each other. When a trace session is destroyed, all its trace settings are automatically cleaned up.

    Example:

    %% Create a tracer process that will receive the trace events
    -1> Tracer = spawn(fun F() -> receive M -> io:format("~p~n",[M]), F() end end).
    +1> Tracer = spawn(fun F() -> receive M -> io:format("~p~n",[M]), F() end end).
     <0.91.0>
     %% Create a session using the Tracer
    -2> Session = trace:session_create(my_session, Tracer, []).
    -{#Ref<0.1543805153.1548353537.92331>,{my_session, 0}}
    +2> Session = trace:session_create(my_session, Tracer, []).
    +{#Ref<0.1543805153.1548353537.92331>,{my_session, 0}}
     %% Setup call tracing on self()
    -3> trace:process(Session, self(), true, [call]).
    +3> trace:process(Session, self(), true, [call]).
     1
     %% Setup call tracing on lists:seq/2
    -4> trace:function(Session, {lists,seq,2}, [], []).
    +4> trace:function(Session, {lists,seq,2}, [], []).
     1
     %% Call the traced function
    -5> lists:seq(1, 10).
    -{trace,<0.89.0>,call,{lists,seq,[1,10]}} % The trace message
    -[1,2,3,4,5,6,7,8,9,10] % The return value
    +5> lists:seq(1, 10).
    +{trace,<0.89.0>,call,{lists,seq,[1,10]}} % The trace message
    +[1,2,3,4,5,6,7,8,9,10] % The return value
     %% Cleanup the trace session
    -6> trace:session_destroy(Session).
    +6> trace:session_destroy(Session).
     ok

    Node Local Tracing Only

    The functions in this module only operates on the local node. That is, both the traced processes/ports as well as the tracer process/port/module must all reside on the same local node as the call is made. To trace remote nodes use dbg or @@ -1328,9 +1328,9 @@ Match Specifications in Erlang in the User's Guide for the ERTS application.

  • true - Enable tracing for all received messages (to 'receive' traced processes). Any match specification is removed. This is the default.

  • false - Disable tracing for all received messages. Any match -specification is removed.

  • Argument FlagList must be [] for receive tracing.

    The return value is always 1.

    Examples:

    Only trace messages from a specific process Pid:

    > trace:recv(Session, [{['_',Pid, '_'],[],[]}], []).
    -1

    Only trace messages matching {reply, _}:

    > trace:recv(Session, [{['_','_', {reply,'_'}],[],[]}], []).
    -1

    Only trace messages from other nodes:

    > trace:recv(Session, [{['$1', '_', '_'],[{'=/=','$1',{node}}],[]}], []).
    +specification is removed.

    Argument FlagList must be [] for receive tracing.

    The return value is always 1.

    Examples:

    Only trace messages from a specific process Pid:

    > trace:recv(Session, [{['_',Pid, '_'],[],[]}], []).
    +1

    Only trace messages matching {reply, _}:

    > trace:recv(Session, [{['_','_', {reply,'_'}],[],[]}], []).
    +1

    Only trace messages from other nodes:

    > trace:recv(Session, [{['$1', '_', '_'],[{'=/=','$1',{node}}],[]}], []).
     1

    Note

    A match specification for 'receive' trace can use all guard and body functions except caller, is_seq_trace, get_seq_token, set_seq_token, enable_trace, disable_trace, trace, silent, and process_dump.

    Fails by raising an error exception with an error reason of:

    • badarg - If an argument is invalid.

    • system_limit - If a match specification passed as argument has excessive @@ -1381,10 +1381,10 @@ Match Specifications in Erlang in the User's Guide for the ERTS application.

    • true - Enable tracing for all sent messages (from send traced processes). Any match specification is removed.

    • false - Disable tracing for all sent messages. Any match specification -is removed.

    Argument FlagList must be [].

    The return value is always 1.

    Examples:

    Only trace messages to a specific process Pid:

    > trace:send(Session, [{[Pid, '_'],[],[]}], []).
    -1

    Only trace messages matching {reply, _}:

    > trace:send(Session, [{['_', {reply,'_'}],[],[]}], []).
    -1

    Only trace messages sent to the sender itself:

    > trace:send(Session, [{['$1', '_'],[{'=:=','$1',{self}}],[]}], []).
    -1

    Only trace messages sent to other nodes:

    > trace:send(Session, [{['$1', '_'],[{'=/=',{node,'$1'},{node}}],[]}], []).
    +is removed.

    Argument FlagList must be [].

    The return value is always 1.

    Examples:

    Only trace messages to a specific process Pid:

    > trace:send(Session, [{[Pid, '_'],[],[]}], []).
    +1

    Only trace messages matching {reply, _}:

    > trace:send(Session, [{['_', {reply,'_'}],[],[]}], []).
    +1

    Only trace messages sent to the sender itself:

    > trace:send(Session, [{['$1', '_'],[{'=:=','$1',{self}}],[]}], []).
    +1

    Only trace messages sent to other nodes:

    > trace:send(Session, [{['$1', '_'],[{'=/=',{node,'$1'},{node}}],[]}], []).
     1

    Note

    A match specification for send trace can use all guard and body functions except caller.

    Fails by raising an error exception with an error reason of:

    • badarg - If an argument is invalid.

    • system_limit - If a match specification passed as argument has excessive nesting which causes scheduler stack exhaustion for the scheduler that the /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1841)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger.html 2026-08-21 04:00:24.371326970 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger.html 2026-08-21 04:00:24.371326970 +0000 @@ -95,20 +95,20 @@

      API module for Logger, the standard logging facility in Erlang/OTP.

      This module implements the main API for logging in Erlang/OTP. To create a log event, use the API functions or the log -macros, for example:

      ?LOG_ERROR("error happened because: ~p", [Reason]).   % With macro
      -logger:error("error happened because: ~p", [Reason]). % Without macro

      To configure the Logger backend, use +macros, for example:

      ?LOG_ERROR("error happened because: ~p", [Reason]).   % With macro
      +logger:error("error happened because: ~p", [Reason]). % Without macro

      To configure the Logger backend, use Kernel configuration parameters or configuration functions in the Logger API.

      By default, the Kernel application installs one log handler at system start. This handler is named default. It receives and processes standard log events produced by the Erlang runtime system, standard behaviours and different Erlang/OTP applications. The log events are by default printed to the terminal.

      If you want your systems logs to be printed to a file instead, you must configure the default handler to do so. The simplest way is to include the -following in your sys.config:

      [{kernel,
      -  [{logger,
      -    [{handler, default, logger_std_h,
      -      #href_anchor"ss">config => #{file => "path/to/file.log"}}}]}]}].

      For more information about:

      • the Logger facility in general, see the User's Guide.
      • how to configure Logger, see the +following in your sys.config:

        [{kernel,
        +  [{logger,
        +    [{handler, default, logger_std_h,
        +      #href_anchor"ss">config => #{file => "path/to/file.log"}}}]}]}].

        For more information about:

        Macros

        The following macros are defined in logger.hrl, which is included in a module -with the directive

            -include_lib("kernel/include/logger.hrl").
        • ?LOG_EMERGENCY(StringOrReport[,Metadata])
        • ?LOG_EMERGENCY(FunOrFormat,Args[,Metadata])
        • ?LOG_ALERT(StringOrReport[,Metadata])
        • ?LOG_ALERT(FunOrFormat,Args[,Metadata])
        • ?LOG_CRITICAL(StringOrReport[,Metadata])
        • ?LOG_CRITICAL(FunOrFormat,Args[,Metadata])
        • ?LOG_ERROR(StringOrReport[,Metadata])
        • ?LOG_ERROR(FunOrFormat,Args[,Metadata])
        • ?LOG_WARNING(StringOrReport[,Metadata])
        • ?LOG_WARNING(FunOrFormat,Args[,Metadata])
        • ?LOG_NOTICE(StringOrReport[,Metadata])
        • ?LOG_NOTICE(FunOrFormat,Args[,Metadata])
        • ?LOG_INFO(StringOrReport[,Metadata])
        • ?LOG_INFO(FunOrFormat,Args[,Metadata])
        • ?LOG_DEBUG(StringOrReport[,Metadata])
        • ?LOG_DEBUG(FunOrFormat,Args[,Metadata])
        • ?LOG(Level,StringOrReport[,Metadata])
        • ?LOG(Level,FunOrFormat,Args[,Metadata])

        All macros expand to a call to Logger, where Level is taken from the macro +with the directive

            -include_lib("kernel/include/logger.hrl").
        • ?LOG_EMERGENCY(StringOrReport[,Metadata])
        • ?LOG_EMERGENCY(FunOrFormat,Args[,Metadata])
        • ?LOG_ALERT(StringOrReport[,Metadata])
        • ?LOG_ALERT(FunOrFormat,Args[,Metadata])
        • ?LOG_CRITICAL(StringOrReport[,Metadata])
        • ?LOG_CRITICAL(FunOrFormat,Args[,Metadata])
        • ?LOG_ERROR(StringOrReport[,Metadata])
        • ?LOG_ERROR(FunOrFormat,Args[,Metadata])
        • ?LOG_WARNING(StringOrReport[,Metadata])
        • ?LOG_WARNING(FunOrFormat,Args[,Metadata])
        • ?LOG_NOTICE(StringOrReport[,Metadata])
        • ?LOG_NOTICE(FunOrFormat,Args[,Metadata])
        • ?LOG_INFO(StringOrReport[,Metadata])
        • ?LOG_INFO(FunOrFormat,Args[,Metadata])
        • ?LOG_DEBUG(StringOrReport[,Metadata])
        • ?LOG_DEBUG(FunOrFormat,Args[,Metadata])
        • ?LOG(Level,StringOrReport[,Metadata])
        • ?LOG(Level,FunOrFormat,Args[,Metadata])

        All macros expand to a call to Logger, where Level is taken from the macro name, or from the first argument in the case of the ?LOG macro. Location data is added to the metadata as described under the metadata/0 type definition.

        The call is wrapped in a case statement and will be evaluated only if Level is equal to or below the configured log level.

        See Also

        config, erlang, io, logger_disk_log_h, @@ -1805,26 +1805,26 @@ consistent no matter which handler the system uses. Normal usage is to add a call to logger:add_handlers/1 just after the processes that the handler needs are started, and pass the application's logger configuration as the argument. -For example:

        -behaviour(application).
        -start(_, []) ->
        -    case supervisor:start_link({local, my_sup}, my_sup, []) of
        -        {ok, Pid} ->
        -            ok = logger:add_handlers(my_app),
        -            {ok, Pid, []};
        +For example:

        -behaviour(application).
        +start(_, []) ->
        +    case supervisor:start_link({local, my_sup}, my_sup, []) of
        +        {ok, Pid} ->
        +            ok = logger:add_handlers(my_app),
        +            {ok, Pid, []};
                 Error -> Error
              end.

        This reads the logger configuration parameter from the my_app application and starts the configured handlers. The contents of the configuration use the same rules as the logger handler configuration.

        If the handler is meant to replace the default handler, the Kernel's default handler have to be disabled before the new handler is added. A sys.config file -that disables the Kernel handler and adds a custom handler could look like this:

        [{kernel,
        -  [{logger,
        +that disables the Kernel handler and adds a custom handler could look like this:

        [{kernel,
        +  [{logger,
             %% Disable the default Kernel handler
        -    [{handler, default, undefined}]}]},
        - {my_app,
        -  [{logger,
        +    [{handler, default, undefined}]}]},
        + {my_app,
        +  [{logger,
             %% Enable this handler as the default
        -    [{handler, default, my_handler, #{}}]}]}].
        +
        [{handler, default, my_handler, #{}}]}]}].
      @@ -2779,8 +2779,8 @@ -

      Update the formatter configuration for the specified handler.

      The new configuration is merged with the existing formatter configuration.

      To overwrite the existing configuration without any merge, use

      set_handler_config(HandlerId, formatter,
      -	      {FormatterModule, FormatterConfig}).
      +

      Update the formatter configuration for the specified handler.

      The new configuration is merged with the existing formatter configuration.

      To overwrite the existing configuration without any merge, use

      set_handler_config(HandlerId, formatter,
      +	      {FormatterModule, FormatterConfig}).
      @@ -2843,8 +2843,8 @@

      Update configuration data for the specified handler. This function behaves as if -it was implemented as follows:

      {ok, {_, Old}} = logger:get_handler_config(HandlerId),
      -logger:set_handler_config(HandlerId, maps:merge(Old, Config)).

      To overwrite the existing configuration without any merge, use +it was implemented as follows:

      {ok, {_, Old}} = logger:get_handler_config(HandlerId),
      +logger:set_handler_config(HandlerId, maps:merge(Old, Config)).

      To overwrite the existing configuration without any merge, use set_handler_config/2 .

      @@ -2937,8 +2937,8 @@

      Update primary configuration data for Logger. This function behaves as if it was -implemented as follows:

      Old = logger:get_primary_config(),
      -logger:set_primary_config(maps:merge(Old, Config)).

      To overwrite the existing configuration without any merge, use +implemented as follows:

      Old = logger:get_primary_config(),
      +logger:set_primary_config(maps:merge(Old, Config)).

      To overwrite the existing configuration without any merge, use set_primary_config/1 .

      @@ -2970,7 +2970,7 @@

      Set or update metadata to use when logging from current process

      If process metadata exists for the current process, this function behaves as if -it was implemented as follows:

      logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).

      If no process metadata exists, the function behaves as +it was implemented as follows:

      logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).

      If no process metadata exists, the function behaves as set_process_metadata/1 .

      @@ -3002,8 +3002,8 @@

      Update configuration data for the Logger proxy. This function behaves as if it -was implemented as follows:

      Old = logger:get_proxy_config(),
      -logger:set_proxy_config(maps:merge(Old, Config)).

      To overwrite the existing configuration without any merge, use +was implemented as follows:

      Old = logger:get_proxy_config(),
      +logger:set_proxy_config(maps:merge(Old, Config)).

      To overwrite the existing configuration without any merge, use set_proxy_config/1 .

      For more information about the proxy, see section Logger Proxy in the Kernel User's Guide.

      @@ -3666,13 +3666,13 @@

      Create a log event at the given log level, with the given message to be logged and metadata.

      Example:

      %% A plain string
      -1> logger:log(info, "Hello World").
      +1> logger:log(info, "Hello World").
       %% A plain string with metadata
      -2> logger:log(debug, "Hello World", #{ meta => data }).
      +2> logger:log(debug, "Hello World", #{ meta => data }).
       %% A format string with arguments
      -3> logger:log(warning, "The roof is on ~ts",[Cause]).
      +3> logger:log(warning, "The roof is on ~ts",[Cause]).
       %% A report
      -4> logger:log(warning, #{ what => roof, cause => Cause }).

      Equivalent to log(Level, FormatOrFun, Args, #{}) if called as +4> logger:log(warning, #{ what => roof, cause => Cause }).

    Equivalent to log(Level, FormatOrFun, Args, #{}) if called as log(Level, FormatOrFun, Args).

    @@ -3711,12 +3711,12 @@ useful in scenarios when the message/metadata is very expensive to compute. This is because the fun is only evaluated when the message/metadata is actually needed, which may be not at all if the log event is not to be logged. Examples:

    %% A plain string with expensive metadata
    -1> logger:info(fun([]) -> {"Hello World", #{ meta => expensive() }} end,[]).
    +1> logger:info(fun([]) -> {"Hello World", #{ meta => expensive() }} end,[]).
     %% An expensive report
    -2> logger:debug(fun(What) -> #{ what => What, cause => expensive() } end,roof).
    +2> logger:debug(fun(What) -> #{ what => What, cause => expensive() } end,roof).
     %% A plain string with expensive metadata and normal metadata
    -3> logger:debug(fun([]) -> {"Hello World", #{ meta => expensive() }} end,[],
    -               #{ meta => data }).

    When metadata is given both as an argument and returned from the fun they are +3> logger:debug(fun([]) -> {"Hello World", #{ meta => expensive() }} end,[], + #{ meta => data }).

    When metadata is given both as an argument and returned from the fun they are merged. If equal keys exists the values are taken from the metadata returned by the fun.

    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1531)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_chapter.html 2026-08-21 04:00:24.403327179 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_chapter.html 2026-08-21 04:00:24.403327179 +0000 @@ -142,7 +142,7 @@ up to the handler implementation if other processes are involved or not.

    The handlers are called in sequence, and the order is not defined.

    Logger API

    The API for logging consists of a set of macros, and a set of functions of the form logger:Level/1,2,3, which are all shortcuts for logger:log(Level,Arg1[,Arg2[,Arg3]]).

    The macros are defined in logger.hrl, which is included in a module with the -directive

    -include_lib("kernel/include/logger.hrl").

    The difference between using the macros and the exported functions is that +directive

    -include_lib("kernel/include/logger.hrl").

    The difference between using the macros and the exported functions is that macros add location (originator) information to the metadata, and performs lazy evaluation by wrapping the logger call in a case statement, so it is only evaluated if the log level of the event passes the primary log level check.

    Log Level

    The log level indicates the severity of a event. In accordance with the Syslog @@ -152,23 +152,23 @@ must always use the atom. To compare the severity of two log levels, use logger:compare_levels/2.

    Log Message

    The log message contains the information to be logged. The message can consist of a format string and arguments (given as two separate parameters in the Logger -API), a string or a report.

    Example, format string and arguments:

    logger:error("The file does not exist: ~ts",[Filename])

    Example, string:

    logger:notice("Something strange happened!")

    A report, which is either a map or a key-value list, is the preferred way to log +API), a string or a report.

    Example, format string and arguments:

    logger:error("The file does not exist: ~ts",[Filename])

    Example, string:

    logger:notice("Something strange happened!")

    A report, which is either a map or a key-value list, is the preferred way to log using Logger as it makes it possible for different backends to filter and format -the log event as it needs to.

    Example, report:

    ?LOG_ERROR(#{ user => joe, filename => Filename, reason => enoent })

    Reports can be accompanied by a report callback specified in the log event's +the log event as it needs to.

    Example, report:

    ?LOG_ERROR(#{ user => joe, filename => Filename, reason => enoent })

    Reports can be accompanied by a report callback specified in the log event's metadata. The report callback is a convenience function that the formatter can use to convert the report to a format string and arguments, or directly to a string. The formatter can also use its own conversion function, if no callback is provided, or if a customized formatting is desired.

    The report callback must be a fun with one or two arguments. If it takes one argument, this is the report itself, and the fun returns a format string and -arguments:

    fun((logger:report()) -> {io:format(),[term()]})

    If it takes two arguments, the first is the report, and the second is a map -containing extra data that allows direct conversion to a string:

    fun((logger:report(),logger:report_cb_config()) -> unicode:chardata())

    The fun must obey the depth and chars_limit parameters provided in the +arguments:

    fun((logger:report()) -> {io:format(),[term()]})

    If it takes two arguments, the first is the report, and the second is a map +containing extra data that allows direct conversion to a string:

    fun((logger:report(),logger:report_cb_config()) -> unicode:chardata())

    The fun must obey the depth and chars_limit parameters provided in the second argument, as the formatter cannot do anything useful of these parameters with the returned string. The extra data also contains a field named single_line, indicating if the printed log message may contain line breaks or not. This variant is used when the formatting of the report depends on the size -or single line parameters.

    Example, report, and metadata with report callback:

    logger:debug(#{got => connection_request, id => Id, state => State},
    -             #{report_cb => fun(R) -> {"~p",[R]} end})

    The log message can also be provided through a fun for lazy evaluation. The fun +or single line parameters.

    Example, report, and metadata with report callback:

    logger:debug(#{got => connection_request, id => Id, state => State},
    +             #{report_cb => fun(R) -> {"~p",[R]} end})

    The log message can also be provided through a fun for lazy evaluation. The fun is only evaluated if the primary log level check passes, and is therefore recommended if it is expensive to generate the message. The lazy fun must return a string, a report, or a tuple with format string and arguments.

    Metadata

    Metadata contains additional data associated with a log message. Logger inserts @@ -307,12 +307,12 @@ proxy configuration.

    Config is any (zero or more) of the following:

    • {handler, default, undefined} - Disables the default handler. This allows another application to add its own default handler.

      Only one entry of this type is allowed.

    • {handler, HandlerId, Module, HandlerConfig} - If HandlerId is default, then this entry modifies the default handler, equivalent to -calling

      logger:remove_handler(default)

      followed by

      logger:add_handler(default, Module, HandlerConfig)

      For all other values of HandlerId, this entry adds a new handler, -equivalent to calling

      logger:add_handler(HandlerId, Module, HandlerConfig)

      Multiple entries of this type are allowed.

    • {filters, FilterDefault, [Filter]} - Adds the specified primary -filters.

      • FilterDefault = log | stop

      • Filter = {FilterId, {FilterFun, FilterConfig}}

      Equivalent to calling

      logger:add_primary_filter(FilterId, {FilterFun, FilterConfig})

      for each Filter.

      FilterDefault specifies the behaviour if all primary filters return +calling

      logger:remove_handler(default)

      followed by

      logger:add_handler(default, Module, HandlerConfig)

      For all other values of HandlerId, this entry adds a new handler, +equivalent to calling

      logger:add_handler(HandlerId, Module, HandlerConfig)

      Multiple entries of this type are allowed.

    • {filters, FilterDefault, [Filter]} - Adds the specified primary +filters.

      • FilterDefault = log | stop

      • Filter = {FilterId, {FilterFun, FilterConfig}}

      Equivalent to calling

      logger:add_primary_filter(FilterId, {FilterFun, FilterConfig})

      for each Filter.

      FilterDefault specifies the behaviour if all primary filters return ignore, see section Filters.

      Only one entry of this type is allowed.

    • {module_level, Level, [Module]} - Sets module log level for the given -modules. Equivalent to calling

      logger:set_module_level(Module, Level)

      for each Module.

      Multiple entries of this type are allowed.

    • {proxy, ProxyConfig} - Sets the proxy configuration, equivalent to -calling

      logger:set_proxy_config(ProxyConfig)

      Only one entry of this type is allowed.

    See section Configuration Examples for +modules. Equivalent to calling

    logger:set_module_level(Module, Level)

    for each Module.

    Multiple entries of this type are allowed.

  • {proxy, ProxyConfig} - Sets the proxy configuration, equivalent to +calling

    logger:set_proxy_config(ProxyConfig)

    Only one entry of this type is allowed.

  • See section Configuration Examples for examples using the logger parameter for system configuration.

  • logger_metadata = map() - Specifies the primary metadata. See the kernel(6) manual page for more information about this parameter.

  • logger_level = Level - Specifies the primary log @@ -327,31 +327,31 @@ file. See the config(4) manual page for more information about this file.

    Each of the following examples shows a simple system configuration file that configures Logger according to the description.

    Modify the default handler to print to a file instead of -standard_io:

    [{kernel,
    -  [{logger,
    -    [{handler, default, logger_std_h,  % {handler, HandlerId, Module,
    -      #{config => #{file => "log/erlang.log"}}}  % Config}
    -    ]}]}].

    Modify the default handler to print each log event as a single line:

    [{kernel,
    -  [{logger,
    -    [{handler, default, logger_std_h,
    -      #{formatter => {logger_formatter, #{single_line => true}}}}
    -    ]}]}].

    Modify the default handler to print the pid of the logging process for each log -event:

    [{kernel,
    -  [{logger,
    -    [{handler, default, logger_std_h,
    -      #{formatter => {logger_formatter,
    -                        #{template => [time," ",pid," ",msg,"\n"]}}}}
    -    ]}]}].

    Modify the default handler to only print errors and more severe log events to +standard_io:

    [{kernel,
    +  [{logger,
    +    [{handler, default, logger_std_h,  % {handler, HandlerId, Module,
    +      #{config => #{file => "log/erlang.log"}}}  % Config}
    +    ]}]}].

    Modify the default handler to print each log event as a single line:

    [{kernel,
    +  [{logger,
    +    [{handler, default, logger_std_h,
    +      #{formatter => {logger_formatter, #{single_line => true}}}}
    +    ]}]}].

    Modify the default handler to print the pid of the logging process for each log +event:

    [{kernel,
    +  [{logger,
    +    [{handler, default, logger_std_h,
    +      #{formatter => {logger_formatter,
    +                        #{template => [time," ",pid," ",msg,"\n"]}}}}
    +    ]}]}].

    Modify the default handler to only print errors and more severe log events to "log/erlang.log", and add another handler to print all log events to -"log/debug.log".

    [{kernel,
    -  [{logger,
    -    [{handler, default, logger_std_h,
    -      #{level => error,
    -        config => #{file => "log/erlang.log"}}},
    -     {handler, info, logger_std_h,
    -      #{level => debug,
    -        config => #{file => "log/debug.log"}}}
    -    ]}]}].

    Backwards Compatibility with error_logger

    Logger provides backwards compatibility with error_logger in the following +"log/debug.log".

    [{kernel,
    +  [{logger,
    +    [{handler, default, logger_std_h,
    +      #{level => error,
    +        config => #{file => "log/erlang.log"}}},
    +     {handler, info, logger_std_h,
    +      #{level => debug,
    +        config => #{file => "log/debug.log"}}}
    +    ]}]}].

    Backwards Compatibility with error_logger

    Logger provides backwards compatibility with error_logger in the following ways:

    • API for Logging - The error_logger API still exists, but should only be used by legacy code. It will be removed in a later release.

      Calls to error_logger:error_report/1,2, error_logger:error_msg/1,2, and corresponding @@ -387,9 +387,9 @@ information about the old SASL error logging functionality.

    • Legacy Event Handlers - To use event handlers written for error_logger, just add your event handler with

      error_logger:add_report_handler/1,2.

      This automatically starts the error logger event manager, and adds -error_logger as a handler to Logger, with the following configuration:

      #href_anchor"ss">level => info,
      +error_logger as a handler to Logger, with the following configuration:

      #href_anchor"ss">level => info,
         filter_default => log,
      -  filters => []}.

      Note

      This handler ignores events that do not originate from the error_logger + filters => []}.

      Note

      This handler ignores events that do not originate from the error_logger API, or from within OTP. This means that if your code uses the Logger API for logging, then your log events will be discarded by this handler.

      The handler is not overload protected.

    Error Handling

    Logger does, to a certain extent, check its input data before forwarding a log event to filters and handlers. It does, however, not evaluate report callbacks, @@ -402,20 +402,20 @@ about report callbacks and valid forms of log messages.

    Example: Add a handler to log info events to file

    When starting an Erlang node, the default behaviour is that all log events on level notice or more severe, are logged to the terminal via the default handler. To also log info events, you can either change the primary log level to -info:

    1> logger:set_primary_config(level, info).
    -ok

    or set the level for one or a few modules only:

    2> logger:set_module_level(mymodule, info).
    +info:

    1> logger:set_primary_config(level, info).
    +ok

    or set the level for one or a few modules only:

    2> logger:set_module_level(mymodule, info).
     ok

    This allows info events to pass through to the default handler, and be printed to the terminal as well. If there are many info events, it can be useful to print these to a file instead.

    First, set the log level of the default handler to notice, preventing it from -printing info events to the terminal:

    3> logger:set_handler_config(default, level, notice).
    +printing info events to the terminal:

    3> logger:set_handler_config(default, level, notice).
     ok

    Then, add a new handler which prints to file. You can use the handler module -logger_std_h, and configure it to log to file:

    4> Config = #href_anchor"ss">config => #{file => "./info.log"}, level => info}.
    -#{config => #{file => "./info.log"},level => info}
    -5> logger:add_handler(myhandler, logger_std_h, Config).
    +logger_std_h, and configure it to log to file:

    4> Config = #href_anchor"ss">config => #{file => "./info.log"}, level => info}.
    +#{config => #{file => "./info.log"},level => info}
    +5> logger:add_handler(myhandler, logger_std_h, Config).
     ok

    Since filter_default defaults to log, this handler now receives all log events. If you want info events only in the file, you must add a filter to stop -all non-info events. The built-in filter logger_filters:level/2 can do this:

    6> logger:add_handler_filter(myhandler, stop_non_info,
    -                             {fun logger_filters:level/2, {stop, neq, info}}).
    +all non-info events. The built-in filter logger_filters:level/2 can do this:

    6> logger:add_handler_filter(myhandler, stop_non_info,
    +                             {fun logger_filters:level/2, {stop, neq, info}}).
     ok

    See section Filters for more information about the filters and the filter_default configuration parameter.

    Example: Implement a handler

    logger_handler describes the callback functions that can be implemented for a Logger handler.

    A handler callback module must export:

    • log(Log, Config)

    It can optionally also export some, or all, of the following:

    • adding_handler(Config)
    • removing_handler(Config)
    • changing_config(SetOrUpdate, OldConfig, NewConfig)
    • filter_config(Config)

    When a handler is added, by for example a call to @@ -434,48 +434,48 @@ database.

    When logger:get_config/0 or logger:get_handler_config/0,1 is called, Logger calls HModule:filter_config(Config). This function must return the -handler configuration where internal data is removed.

    A simple handler that prints to the terminal can be implemented as follows:

    -module(myhandler1).
    --export([log/2]).
    +handler configuration where internal data is removed.

    A simple handler that prints to the terminal can be implemented as follows:

    -module(myhandler1).
    +-export([log/2]).
     
    -log(LogEvent, #{formatter := {FModule, FConfig}}) ->
    -    io:put_chars(FModule:format(LogEvent, FConfig)).

    Notice that the above handler does not have any overload protection, and all log +log(LogEvent, #{formatter := {FModule, FConfig}}) -> + io:put_chars(FModule:format(LogEvent, FConfig)).

    Notice that the above handler does not have any overload protection, and all log events are printed directly from the client process.

    For information and examples of overload protection, please refer to section Protecting the Handler from Overload, and the implementation of logger_std_h and logger_disk_log_h .

    The following is a simpler example of a handler which logs to a file through one -single process:

    -module(myhandler2).
    --export([adding_handler/1, removing_handler/1, log/2]).
    --export([init/1, handle_call/3, handle_cast/2, terminate/2]).
    +single process:

    -module(myhandler2).
    +-export([adding_handler/1, removing_handler/1, log/2]).
    +-export([init/1, handle_call/3, handle_cast/2, terminate/2]).
     
    -adding_handler(Config) ->
    -    MyConfig = maps:get(config,Config,#href_anchor"ss">file => "myhandler2.log"}),
    -    {ok, Pid} = gen_server:start(?MODULE, MyConfig, []),
    -    {ok, Config#{config => MyConfig#{pid => Pid}}}.
    +adding_handler(Config) ->
    +    MyConfig = maps:get(config,Config,#href_anchor"ss">file => "myhandler2.log"}),
    +    {ok, Pid} = gen_server:start(?MODULE, MyConfig, []),
    +    {ok, Config#{config => MyConfig#{pid => Pid}}}.
     
    -removing_handler(#{config := #{pid := Pid}}) ->
    -    gen_server:stop(Pid).
    +removing_handler(#{config := #{pid := Pid}}) ->
    +    gen_server:stop(Pid).
     
    -log(LogEvent,#{config := #{pid := Pid}} = Config) ->
    -    gen_server:cast(Pid, {log, LogEvent, Config}).
    +log(LogEvent,#{config := #{pid := Pid}} = Config) ->
    +    gen_server:cast(Pid, {log, LogEvent, Config}).
     
    -init(#{file := File}) ->
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_cookbook.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1537))
    --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_cookbook.html	2026-08-21 04:00:24.430327354 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_cookbook.html	2026-08-21 04:00:24.430327354 +0000
    @@ -96,13 +96,13 @@
     post
     Erlang/OTP 21's new logger is
     a great starting point.

    Note

    If you find that some common Logger usage is missing from this guide, please -open a pull request on github with the suggested addition

    Get Logger information

    1> logger:i(primary).
    +open a pull request on github with the suggested addition

    Get Logger information

    1> logger:i(primary).
     Primary configuration:
         Level: notice
         Filter Default: log
         Filters:
    -        (none)

    It is also possible to fetch the configuration using -logger:get_primary_config().

    See also

    2> logger:i(handlers).
    +        (none)

    It is also possible to fetch the configuration using +logger:get_primary_config().

    See also

    2> logger:i(handlers).
     Handler configuration:
         Id: default
             Module: logger_std_h
    @@ -119,10 +119,10 @@
                     Arg: stop
                 Id: domain
                     Fun: fun logger_filters:domain/2
    -                Arg: {log,super,[otp,sasl]}
    +                Arg: {log,super,[otp,sasl]}
                 Id: no_domain
                     Fun: fun logger_filters:domain/2
    -                Arg: {log,undefined,[]}
    +                Arg: {log,undefined,[]}
             Handler Config:
                 burst_limit_enable: true
                 burst_limit_max_count: 500
    @@ -149,69 +149,69 @@
     =PROGRESS REPORT==== 4-Nov-2019::16:33:11.746546 ===
         application: stdlib
         started_at: nonode@nohost
    -Eshell V10.5.3  (abort with ^G)
    +Eshell V10.5.3  (abort with ^G)
     1>

    Configure Logger formatter

    In order to fit better into your existing logging infrastructure Logger can format its logging messages any way you want to. Either you can use the built-in formatter, or you can build your own.

    Single line configuration

    Since single line logging is the default of the built-in formatter you only have to provide the empty map as the configuration. The example below uses the sys.config to change the formatter configuration.

    $ cat sys.config
    -[{kernel,
    -  [{logger,
    -    [{handler, default, logger_std_h,
    -      #{ formatter => {logger_formatter, #{ }}}}]}]}].
    +[{kernel,
    +  [{logger,
    +    [{handler, default, logger_std_h,
    +      #{ formatter => {logger_formatter, #{ }}}}]}]}].
     $ erl -config sys
    -Eshell V10.5.1  (abort with ^G)
    -1> logger:error("Oh noes, an error").
    +Eshell V10.5.1  (abort with ^G)
    +1> logger:error("Oh noes, an error").
     1962-10-03T11:07:47.466763-04:00 error: Oh noes, an error

    However, if you just want to change it for the current session you can also do -that.

    1> logger:set_handler_config(default, formatter, {logger_formatter, #{}}).
    +that.

    1> logger:set_handler_config(default, formatter, {logger_formatter, #{}}).
     ok
    -2> logger:error("Oh noes, another error").
    +2> logger:error("Oh noes, another error").
     1962-10-04T15:34:02.648713-04:00 error: Oh noes, another error

    See also

    Add file and line number to log entries

    You can change what is printed to the log by using the formatter template:

    $ cat sys.config
    -[{kernel,
    -  [{logger,
    -    [{handler, default, logger_std_h,
    -      #{ formatter => {logger_formatter,
    -        #{ template => [time," ", file,":",line," ",level,": ",msg,"\n"] }}}}]}]}].
    +[{kernel,
    +  [{logger,
    +    [{handler, default, logger_std_h,
    +      #{ formatter => {logger_formatter,
    +        #{ template => [time," ", file,":",line," ",level,": ",msg,"\n"] }}}}]}]}].
     $ erl -config sys
    -Eshell V10.5.1  (abort with ^G)
    -1> logger:error("Oh noes, more errors",#{ file => "shell.erl", line => 1 }).
    +Eshell V10.5.1  (abort with ^G)
    +1> logger:error("Oh noes, more errors",#{ file => "shell.erl", line => 1 }).
     1962-10-05T07:37:44.104241+02:00 shell.erl:1 error: Oh noes, more errors

    Note that file and line have to be added in the metadata by the caller of logger:log/3 as otherwise Logger will not know from where it was called. The file and line number are automatically added if you use the ?LOG_ERROR macros in kernel/include/logger.hrl.

    See also

    Configuring handlers

    Instead of printing the logs to stdout we print them to a rotating file log.

    $ cat sys.config
    -[{kernel,
    -  [{logger,
    -    [{handler, default, logger_std_h,
    -      #{ config => #{ file => "log/erlang.log",
    +[{kernel,
    +  [{logger,
    +    [{handler, default, logger_std_h,
    +      #{ config => #{ file => "log/erlang.log",
                           max_no_bytes => 4096,
    -                      max_no_files => 5},
    -         formatter => {logger_formatter, #{}}}}]}]}].
    +                      max_no_files => 5},
    +         formatter => {logger_formatter, #{}}}}]}]}].
     $ erl -config sys
    -Eshell V10.5.1  (abort with ^G)
    -1> logger:error("Oh noes, even more errors").
    +Eshell V10.5.1  (abort with ^G)
    +1> logger:error("Oh noes, even more errors").
     ok
    -2> erlang:halt().
    +2> erlang:halt().
     $ cat log/erlang.log
     2019-10-07T11:47:16.837958+02:00 error: Oh noes, even more errors

    See also

    Debug only handler

    Add a handler that prints debug log events to a file, while the default handler prints only up to notice level events to standard out.

    $ cat sys.config
    -[{kernel,
    -  [{logger_level, all},
    -   {logger,
    -    [{handler, default, logger_std_h,
    -      #{ level => notice }},
    -     {handler, debug, logger_std_h,
    -      #{ filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],
    -         config => #{ file => "log/debug.log" } }}
    -    ]}]}].
    +[{kernel,
    +  [{logger_level, all},
    +   {logger,
    +    [{handler, default, logger_std_h,
    +      #{ level => notice }},
    +     {handler, debug, logger_std_h,
    +      #{ filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],
    +         config => #{ file => "log/debug.log" } }}
    +    ]}]}].
     $ erl -config sys
    -Eshell V10.5.1  (abort with ^G)
    -1> logger:error("Oh noes, even more errors").
    +Eshell V10.5.1  (abort with ^G)
    +1> logger:error("Oh noes, even more errors").
     =ERROR REPORT==== 9-Oct-2019::14:40:54.784162 ===
     Oh noes, even more errors
     ok
    -2> logger:debug("A debug event").
    +2> logger:debug("A debug event").
     ok
    -3> erlang:halt().
    +3> erlang:halt().
     $ cat log/debug.log
     2019-10-09T14:41:03.680541+02:00 debug: A debug event

    In the configuration above we first raise the primary log level to max in order for the debug log events to get to the handlers. Then we configure the default @@ -219,30 +219,30 @@ is all. Then the debug handler is configured with a filter to stop any log message that is not a debug level message.

    It is also possible to do the same changes in an already running system using the logger module. Then you do like this:

    $ erl
    -1> logger:set_handler_config(default, level, notice).
    +1> logger:set_handler_config(default, level, notice).
     ok
    -2> logger:add_handler(debug, logger_std_h, #{
    -  filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],
    -  config => #{ file => "log/debug.log" } }).
    +2> logger:add_handler(debug, logger_std_h, #{
    +  filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],
    +  config => #{ file => "log/debug.log" } }).
     ok
    -3> logger:set_primary_config(level, all).
    +3> logger:set_primary_config(level, all).
     ok

    It is important that you do not raise the primary log level before adjusting the default handler's level as otherwise your standard out may be flooded by debug log messages.

    See also

    Logging

    What to log and how

    The simplest way to log something is by using the Logger macros and give a -report to the macro. For example if you want to log an error:

    ?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP }).

    This will print the following in the default log:

    =ERROR REPORT==== 10-Oct-2019::12:13:10.089073 ===
    +report to the macro. For example if you want to log an error:

    ?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP }).

    This will print the following in the default log:

    =ERROR REPORT==== 10-Oct-2019::12:13:10.089073 ===
         dst: {8,8,4,4}
         src: {8,8,8,8}
         status: 418
         what: http_error

    or the below if you use a single line formatter:

    2019-10-10T12:14:11.921843+02:00 error: dst: {8,8,4,4}, src: {8,8,8,8}, status: 418, what: http_error

    See also

    Report call-backs and printing of events

    If you want to do structured logging, but still want to have some control of how the final log message is formatted you can give a report_cb as part of the -metadata with your log event.

    ReportCB = fun(#{ what := What, status := Status, src := Src, dst := Dst }) ->
    -                   {ok, #hostent{ h_name = SrcName }} = inet:gethostbyaddr(Src),
    -                   {ok, #hostent{ h_name = DstName }} = inet:gethostbyaddr(Dst),
    -                   {"What: ~p~nStatus: ~p~nSrc: ~s (~s)~nDst: ~s (~s)~n",
    -                    [What, Status, inet:ntoa(Src), SrcName, inet:ntoa(Dst), DstName]}
    +metadata with your log event.

    ReportCB = fun(#{ what := What, status := Status, src := Src, dst := Dst }) ->
    +                   {ok, #hostent{ h_name = SrcName }} = inet:gethostbyaddr(Src),
    +                   {ok, #hostent{ h_name = DstName }} = inet:gethostbyaddr(Dst),
    +                   {"What: ~p~nStatus: ~p~nSrc: ~s (~s)~nDst: ~s (~s)~n",
    +                    [What, Status, inet:ntoa(Src), SrcName, inet:ntoa(Dst), DstName]}
                end,
    -?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP },
    -           #{ report_cb => ReportCB }).

    This will print the following:

    =ERROR REPORT==== 10-Oct-2019::13:29:02.230863 ===
    +?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP },
    +           #{ report_cb => ReportCB }).

    This will print the following:

    =ERROR REPORT==== 10-Oct-2019::13:29:02.230863 ===
     What: http_error
     Status: 418
     Src: 8.8.8.8 (dns.google)
    @@ -251,22 +251,22 @@
     single line formatter, however you can also use a report_cb fun with 2 arguments
     where the second argument is the formatting options.

    See also

    Filters

    Filters are used to remove or change log events before they reach the handlers.

    Process filters

    If we only want debug messages from a specific process it is possible to do this with a filter like this:

    %% Initial setup to use a filter for the level filter instead of the primary level
    -PrimaryLevel = maps:get(level, logger:get_primary_config()),
    -ok = logger:add_primary_filter(primary_level,
    -    {fun logger_filters:level/2, {log, gteq, PrimaryLevel}}),
    -logger:set_primary_config(filter_default, stop),
    -logger:set_primary_config(level, all),
    +PrimaryLevel = maps:get(level, logger:get_primary_config()),
    +ok = logger:add_primary_filter(primary_level,
    +    {fun logger_filters:level/2, {log, gteq, PrimaryLevel}}),
    +logger:set_primary_config(filter_default, stop),
    +logger:set_primary_config(level, all),
     
     %% Test that things work as they should
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_disk_log_h.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
    --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_disk_log_h.html	2026-08-21 04:00:24.451327491 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_disk_log_h.html	2026-08-21 04:00:24.451327491 +0000
    @@ -129,12 +129,12 @@
     and the disk_log handler, and are documented in the
     User's Guide.

    Notice that when changing the configuration of the handler in runtime, the disk_log options (file, type, max_no_files, max_no_bytes) must not be -modified.

    Example of adding a disk_log handler:

    logger:add_handler(my_disk_log_h, logger_disk_log_h,
    -                   #{config => #{file => "./my_disk_log",
    +modified.

    Example of adding a disk_log handler:

    logger:add_handler(my_disk_log_h, logger_disk_log_h,
    +                   #{config => #{file => "./my_disk_log",
                                      type => wrap,
                                      max_no_files => 4,
                                      max_no_bytes => 10000,
    -                                 filesync_repeat_interval => 1000}}).

    To use the disk_log handler instead of the default standard handler when + filesync_repeat_interval => 1000}}).

    To use the disk_log handler instead of the default standard handler when starting an Erlang node, change the Kernel default logger to use logger_disk_log_h. Example:

    erl -kernel logger '[{handler,default,logger_disk_log_h,
                           #{config => #{file => "./system_disk_log"}}}]'

    See Also

    logger, logger_std_h, disk_log

    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_filters.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1103)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_filters.html 2026-08-21 04:00:24.470327615 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_filters.html 2026-08-21 04:00:24.471327621 +0000 @@ -210,8 +210,8 @@ events from, for example, a specific functional area. This allows filtering or other specialized treatment in a Logger handler.

    A domain field must be a list of atoms, creating smaller and more specialized domains as the list grows longer. The greatest domain is [], which comprises -all possible domains.

    For example, consider the following domains:

    D1 = [otp]
    -D2 = [otp, sasl]

    D1 is the greatest of the two, and is said to be a super-domain of D2. D2 +all possible domains.

    For example, consider the following domains:

    D1 = [otp]
    +D2 = [otp, sasl]

    D1 is the greatest of the two, and is said to be a super-domain of D2. D2 is a sub-domain D1. Both D1 and D2 are sub-domains of [].

    The above domains are used for logs originating from Erlang/OTP. D1 specifies that the log event comes from Erlang/OTP in general, and D2 indicates that the log event is a so called SASL report.

    The Extra parameter to the domain/2 function is specified when @@ -226,11 +226,11 @@ filter matches and Action is stop, the log event is stopped.

    If the filter does not match, it returns ignore, meaning that other filters, or the value of the configuration parameter filter_default, decide if the event is allowed or not.

    Log events that do not contain any domain field, match only when Compare is -equal to undefined or not_equal.

    Example: stop all events with domain [otp, sasl | _]

    1> logger:set_handler_config(h1, filter_default, log). % this is the default
    +equal to undefined or not_equal.

    Example: stop all events with domain [otp, sasl | _]

    1> logger:set_handler_config(h1, filter_default, log). % this is the default
     ok
    -2> Filter = {fun logger_filters:domain/2, {stop, sub, [otp, sasl]}}.
    +2> Filter = {fun logger_filters:domain/2, {stop, sub, [otp, sasl]}}.
     ...
    -3> logger:add_handler_filter(h1, no_sasl, Filter).
    +3> logger:add_handler_filter(h1, no_sasl, Filter).
     ok
    @@ -275,9 +275,9 @@ filter matches if the value of Operator is:

    • neq - and the compare function returns lt or gt.

    • eq - and the compare function returns eq.

    • lt - and the compare function returns lt.

    • gt - and the compare function returns gt.

    • lteq - and the compare function returns lt or eq.

    • gteq - and the compare function returns gt or eq.

    If the filter matches and Action is log, the log event is allowed. If the filter matches and Action is stop, the log event is stopped.

    If the filter does not match, it returns ignore, meaning that other filters, or the value of the configuration parameter filter_default, will decide if the -event is allowed or not.

    Example: only allow debug level log events

    logger:set_handler_config(h1, filter_default, stop).
    -Filter = {fun logger_filters:level/2, {log, eq, debug}}.
    -logger:add_handler_filter(h1, debug_only, Filter).
    +event is allowed or not.

    Example: only allow debug level log events

    logger:set_handler_config(h1, filter_default, stop).
    +Filter = {fun logger_filters:level/2, {log, eq, debug}}.
    +logger:add_handler_filter(h1, debug_only, Filter).
     ok
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_std_h.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_std_h.html 2026-08-21 04:00:24.489327739 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/logger_std_h.html 2026-08-21 04:00:24.489327739 +0000 @@ -150,9 +150,9 @@ protection behaviour. The same parameters are used both in the standard handler and the disk_log handler, and are documented in the User's Guide.

    Notice that if changing the configuration of the handler in runtime, the type, -file, or modes parameters must not be modified.

    Example of adding a standard handler:

    logger:add_handler(my_standard_h, logger_std_h,
    -                   #{config => #{file => "./system_info.log",
    -                                 filesync_repeat_interval => 1000}}).

    To set the default handler, that starts initially with the Kernel application, +file, or modes parameters must not be modified.

    Example of adding a standard handler:

    logger:add_handler(my_standard_h, logger_std_h,
    +                   #{config => #{file => "./system_info.log",
    +                                 filesync_repeat_interval => 1000}}).

    To set the default handler, that starts initially with the Kernel application, to log to file instead of standard_io, change the Kernel default logger configuration. Example:

    erl -kernel logger '[{handler,default,logger_std_h,
                           #{config => #{file => "./log.log"}}}]'

    An example of how to replace the standard handler with a disk_log handler at /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net.html 2026-08-21 04:00:24.513327895 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net.html 2026-08-21 04:00:24.514327901 +0000 @@ -530,13 +530,13 @@

    Interface address filtering selector function/0.

    For each ifaddrs entry, return either true to keep the entry or false to discard the entry.

    For example, to get an interface list which only contains -non-loopback inet interfaces:

    net:getifaddrs(
    -    fun (#{ addr  := #{family := inet},
    -            flags := Flags}) ->
    -          not lists:member(loopback, Flags);
    -        (_) ->
    +non-loopback inet interfaces:

    net:getifaddrs(
    +    fun (#{ addr  := #{family := inet},
    +            flags := Flags}) ->
    +          not lists:member(loopback, Flags);
    +        (_) ->
               false
    -    end).
    +
    end).
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net_adm.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net_adm.html 2026-08-21 04:00:24.541328077 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net_adm.html 2026-08-21 04:00:24.539328064 +0000 @@ -450,8 +450,8 @@

    Returns the names and associated port numbers of the Erlang nodes that epmd -registered at the specified host.

    Similar to epmd -names, see erts:epmd.

    Returns {error, address} if epmd is not operational.

    Example:

    (arne@dunn)1> net_adm:names().
    -{ok,[{"arne",40262}]}
    +registered at the specified host.

    Similar to epmd -names, see erts:epmd.

    Returns {error, address} if epmd is not operational.

    Example:

    (arne@dunn)1> net_adm:names().
    +{ok,[{"arne",40262}]}
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net_kernel.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1008)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net_kernel.html 2026-08-21 04:00:24.568328253 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/net_kernel.html 2026-08-21 04:00:24.568328253 +0000 @@ -97,9 +97,9 @@ operational for distributed Erlang to work. The purpose of this process is to implement parts of the BIFs spawn/4 and spawn_link/4, and to provide monitoring of the network.

    An Erlang node is started using command-line flag -name or -sname:

    $ erl -sname foobar

    It is also possible to call net_kernel:start(foobar, #{}) -directly from the normal Erlang shell prompt:

    1> net_kernel:start(foobar, #{name_domain => shortnames}).
    -{ok,<0.64.0>}
    -(foobar@gringotts)2>

    If the node is started with command-line flag -sname, the node name is +directly from the normal Erlang shell prompt:

    1> net_kernel:start(foobar, #{name_domain => shortnames}).
    +{ok,<0.64.0>}
    +(foobar@gringotts)2>

    If the node is started with command-line flag -sname, the node name is foobar@Host, where Host is the short name of the host (not the fully qualified domain name). If started with flag -name, the node name is foobar@Host, where Host is the fully qualified domain name. For more @@ -679,13 +679,13 @@ delivered before a nodeup message due to a new connection to the same node. Prior to OTP 23.0, this was not guaranteed to be the case.

  • The format of the node status change messages depends on Options. If Options is the empty list or if net_kernel:monitor_nodes/1 is called, the format is as -follows:

    {nodeup, Node} | {nodedown, Node}
    -  Node = node()

    When Options is the empty map or empty list, the caller will only subscribe +follows:

    {nodeup, Node} | {nodedown, Node}
    +  Node = node()

    When Options is the empty map or empty list, the caller will only subscribe for status change messages for visible nodes. That is, only nodes that appear in the result of erlang:nodes/0.

    If Options equals anything other than the empty list, the format of the status -change messages is as follows:

    {nodeup, Node, Info} | {nodedown, Node, Info}
    -  Node = node()
    -  Info = #{Tag => Val} | [{Tag, Val}]

    Info is either a map or a list of 2-tuples. Its content depends on Options. +change messages is as follows:

    {nodeup, Node, Info} | {nodedown, Node, Info}
    +  Node = node()
    +  Info = #{Tag => Val} | [{Tag, Val}]

    Info is either a map or a list of 2-tuples. Its content depends on Options. If Options is a map, Info will also be a map. If Options is a list, Info will also be a list.

    When Options is a map, currently the following associations are allowed:

    • connection_id => boolean() - If the value of the association equals true, a connection_id => ConnectionId association will be included in the @@ -719,23 +719,23 @@ {node_type, visible} tuple will be included in the Info list.

    • nodedown_reason - The tuple {nodedown_reason, Reason} will be included in the Info list for nodedown messages.

      See the documentation of the nodedown_reason => boolean() association -above for information about possible Reason values.

    Example:

    (a@localhost)1> net_kernel:monitor_nodes(true, #{connection_id=>true, node_type=>all, nodedown_reason=>true}).
    +above for information about possible Reason values.

    Example:

    (a@localhost)1> net_kernel:monitor_nodes(true, #{connection_id=>true, node_type=>all, nodedown_reason=>true}).
     ok
    -(a@localhost)2> flush().
    -Shell got {nodeup,b@localhost,
    -                  #{connection_id => 3067552,node_type => visible}}
    -Shell got {nodeup,c@localhost,
    -                  #{connection_id => 13892107,node_type => hidden}}
    -Shell got {nodedown,b@localhost,
    -                    #{connection_id => 3067552,node_type => visible,
    -                      nodedown_reason => connection_closed}}
    -Shell got {nodedown,c@localhost,
    -                    #{connection_id => 13892107,node_type => hidden,
    -                      nodedown_reason => net_tick_timeout}}
    -Shell got {nodeup,b@localhost,
    -                  #{connection_id => 3067553,node_type => visible}}
    +(a@localhost)2> flush().
    +Shell got {nodeup,b@localhost,
    +                  #{connection_id => 3067552,node_type => visible}}
    +Shell got {nodeup,c@localhost,
    +                  #{connection_id => 13892107,node_type => hidden}}
    +Shell got {nodedown,b@localhost,
    +                    #{connection_id => 3067552,node_type => visible,
    +                      nodedown_reason => connection_closed}}
    +Shell got {nodedown,c@localhost,
    +                    #{connection_id => 13892107,node_type => hidden,
    +                      nodedown_reason => net_tick_timeout}}
    +Shell got {nodeup,b@localhost,
    +                  #{connection_id => 3067553,node_type => visible}}
     ok
    -(a@localhost)3>
    +
    (a@localhost)3>
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (22397)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/notes.html 2026-08-21 04:00:24.637328702 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/notes.html 2026-08-21 04:00:24.638328708 +0000 @@ -92,9 +92,9 @@

    This document describes the changes made to the Kernel application.

    Kernel 10.6.3.3

    Fixed Bugs and Malfunctions

    • inet:info/1 could crash when calling for a closing (port) socket.

      Own Id: OTP-20173

    • Handling of the truncation bit in inet_res has been fixed so it properly falls back to querying over TCP after a truncated UDP reply.

      This fixes a bug introduced in OTP-28.4.2 - kernel-10.6.2 making a truncated UDP answer fail to parse and never execute the fallback, instead the name resolve operation fails.

      Own Id: OTP-20199 Aux Id: PR-11247

    Kernel 10.6.3.2

    Fixed Bugs and Malfunctions

    • gen_tcp_socket accept should explicitly inherit the same options as plain gen_tcp.

      Own Id: OTP-20057

    Kernel 10.6.3.1

    Fixed Bugs and Malfunctions

    • Incorrect TOS format when using gen_udp with socket backend

      Own Id: OTP-20131 Aux Id: OTP-20102, GH-10968

    • SCTP peeloff of an IPv6 socket, the peeled-off socket does not inherit the parent options as expected.

      Own Id: OTP-20134 Aux Id: PR-11007

    Kernel 10.6.3

    Fixed Bugs and Malfunctions

    • On Windows, sockets has to be bound when using 'socket'. Therefor when using gen_tcp with inet_backend = socket, gen_tcp_socket bind even if the caller has not provided an explicit bind address. In that case it attempts to locate a "proper" address on its own. But if the connect address is the loopback address, this could lead to an attempt to bind to an external interface. So, this has now been changed so that if the connect address is the loopback address, the loopback address will also be used when binding.

      Own Id: OTP-20104 Aux Id: #href_anchor"kernel-10-6-2" class="section-heading">Kernel 10.6.2

      Fixed Bugs and Malfunctions

      • Before this patch, the Erlang/OTP built-in DNS resolver (inet_res) used a sequential, process-global 16-bit transaction ID for UDP queries and did not implement source port randomization. Response validation relied almost entirely on this ID. Together, this made DNS cache poisoning practical for an attacker who can observe one query or predict the next ID. The design conflicted with RFC 5452 recommendations for mitigating forged DNS answers.

        inet_res is intended for use in trusted network environments and with trusted recursive resolvers. Earlier documentation did not clearly state this deployment assumption, which could lead users to deploy the resolver in environments where faked DNS responses are possible.

        Therefore, the documentation is been updated to clarify that inet_res should only be used in trusted networks and with trusted recursive resolvers.

        The implementation is also improved to use strong random DNS transaction IDs and source ports for every DNS transaction. This should give ample protection against brute forcing fake DNS replies, known as DNS cache poisoning, but it still does not protect against, for example, an adversary in the path of the DNS transaction that can observe the random values before faking malicious replies, an attack known as DNS spoofing.

        For randomization to happen, the Crypto application has to be loaded, which most probably already should be the case for an Erlang node in an exposed network.

        If performance should become an issue, for applications within safe network environments, the previous light weight behaviour can be configured by setting the resolver option random to false.

        Own Id: OTP-20037 Aux Id: CVE-2026-28810, PR-10864

      Kernel 10.6.1

      Fixed Bugs and Malfunctions

      • A vulnerability has been resolved in the (undocumented, unsupported and unused in OTP) inet_dns_tsig module that leads to a validation bypass.

        If a request contained an error code (forbidden by spec), it was treated as a response and skipped the verification of the MAC. The user of the module would then receive an "all ok" response, depending on the use case, this could lead to such things as AXFR or UPDATE being allowed.

        The code has also been tightening up of the client side to make sure too large (bad) MAC sizes cannot be selected and the limit is the output size of the algorithm chosen.

        Own Id: OTP-20012 Aux Id: PR-10825

      Kernel 10.6

      Fixed Bugs and Malfunctions

      • The built in DNS resolver inet_res has been fixed to do a final request assuming that the request name is absolute, as customary for many DNS resolver client libraries.

        Own Id: OTP-19937 Aux Id: GH-10494, PR-10576

      Improvements and New Features

      • Added support for zstd compression in the file module.

        Own Id: OTP-19860 Aux Id: PR-10385

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      Kernel 10.5

      Fixed Bugs and Malfunctions

      • Fixed a shell crash when calling io:getopts() when user_drv process is not responding/terminating

        Own Id: OTP-19812 Aux Id: PR-10283

      • logger:get_handler_config/0 will no longer crash if a logger handler is removed concurrently with that call.

        Own Id: OTP-19837 Aux Id: PR-10308, GH-9997

      • Fixed a bug in the shell that made it incorrectly output a newline after the output already containing a newline but followed by an asci escape sequence.

        Own Id: OTP-19847 Aux Id: GH-10299

      Improvements and New Features

      • Receive buffer allocation has been optimized for socket socket in that an underutilized buffers' content is copied to a freshly allocated binary of the right size instead of being reallocated.

        This optimization was already implemented for the socket:recv/1 functions, but now the same buffer stragegy is shared between all socket receive operations.

        Own Id: OTP-19794 Aux Id: PR-10231

      • Option(s) to create gen_tcp and socket sockets with protocol IPPROTO_MPTCP has been implemented.

        See functions gen_tcp:listen/2, gen_tcp:connect/4 and the type socket:protocol/0.

        Own Id: OTP-19814

      • Support for the socket options TCP_KEEPCNT, TCP_KEEPIDLE, and TCP_KEEPINTVL have been implemented for gen_tcp, as well as TCP_USER_TIMEOUT for both gen_tcp and socket.

        Own Id: OTP-19857 Aux Id: OTP-19814, PR-10390

      • Limit size of sctp_event_subscribe on Linux

        Own Id: OTP-19863 Aux Id: PR-10321

      Kernel 10.4.2

      Fixed Bugs and Malfunctions

      • Fixed a race condition when registering the standard error process.

        Own Id: OTP-19832 Aux Id: PR-10290

      Kernel 10.4.1

      Fixed Bugs and Malfunctions

      • With this change group.erl will not crash when receiving unknown message.

        Own Id: OTP-19796 Aux Id: ERIERL-1264, PR-10248

      Kernel 10.4

      Fixed Bugs and Malfunctions

      • A remote shell can now exit by closing the input stream, without terminating the remote node.

        Own Id: OTP-19667 Aux Id: PR-9912

      • The internal inet_dns_tsig and inet_res modules have been fixed to TSIG verify the correct timestamp.

        In the process two undocumented error code atoms have been corrected to notauth and notzone to adhere to the DNS RFCs. Code that relied on the previous incorrect values may have to be corrected.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19756 Aux Id: PR-10146

      Improvements and New Features

      • The rudimentary DNS resolver inet_res has aqcuired 3 new functions inet_res:gethostbyname/4, inet_res;getbyname/4 and inet_res:gethostbyaddr/3, that all take an option list argument.

        This option list can be used to override the Kernel application's resolver options when calling the inet_res function directly.

        Own Id: OTP-19737 Aux Id: ERIERL-1209, PR-10112

      Kernel 10.3.2

      Fixed Bugs and Malfunctions

      • socket:sendv/3 with 'nowait' sometimes return 'completion' without 'CompletionInfo' (Windows only).

        Own Id: OTP-19661

      • prim_net nif used incorrect encoding for family resulting in non-functional address selection.

        Own Id: OTP-19674

      • socket:accept can return unexpected 'select_sent'.

        Own Id: OTP-19684 Aux Id: ERIERL-1242

      • net_kernel could be blocked for a very long time when selecting distribution module for a connection if the DNS service was slow. This prevented any new connections to be set up during that time.

        Own Id: OTP-19702 Aux Id: ERIERL-1241, PR-10029

      Improvements and New Features

      • Improved documentation of CompletionStatus for asynchronous (nowait) socket operations.

        Own Id: OTP-19670 Aux Id: PR-9930

      Kernel 10.3.1

      Fixed Bugs and Malfunctions

      • Fix bug where calling io:setopts/1 in a shell without the line_history option would always disable line_history. This bug was introduced in Erlang/OTP 28.0.

        Own Id: OTP-19645 Aux Id: GH-9863, PR-9870

      Kernel 10.3

      Fixed Bugs and Malfunctions

      • Fixed an issue where output to the shell would not print the prompt on a new line.

        Own Id: OTP-19228 Aux Id: PR-8820

      • When in shell is in -noshell mode, and in latin1 encoding mode, io requests in latin1 encoding will not be translated to unicode and back to latin1.

        Own Id: OTP-19296 Aux Id: PR-9013

      • Fixed a bug where a composing unicode character would bind to a character not available to the user and deleting that character would cause a crash.

        Own Id: OTP-19297 Aux Id: PR-9005

      • The -noshell mode has been updated to read data lazily from standard input. Before this fix any data would be read greedily which meant that Erlang could consume data not meant for it. It also meant that in order for shell:start_interactive/0 to work on Windows an API that did not support reading of Unicode characters had to be used.

        Own Id: OTP-19313 Aux Id: PR-8962, GH-8113

      • The Erlang shell no longer crashes when a shell prompt ends with an escape sequence.

        Own Id: OTP-19414 Aux Id: PR-9272

      • code:get_doc/1 now works for cover-compiled modules.

        Own Id: OTP-19513 Aux Id: PR-9433

      • An infinite loop in CNAME loop detection that can cause Out Of Memory has been fixed. This affected CNAME lookup with the internal DNS resolver.

        Own Id: OTP-19544 Aux Id: PR-9587, OTP-19545

      • The internal resolver framework has been fixed to wait with the first resolver lookup until the ERL_INETRC environment variable has been applied.

        Previously, on some platform(s) (Linux) a first lookup when figuring out the domain name was always placed on the native resolver even if ERL_INETRC was used to disable it.

        Own Id: OTP-19555 Aux Id: PR-9543

      • Fix logger:add_handler(default, ...) to correctly replay events generated during startup when the default logger is set to undefined in logger's configuration parameters.

        Own Id: OTP-19588 Aux Id: PR-9595, GH-9436

      • Enhance specs of timeout for improving documentation and dialyzer analysis.

        Own Id: OTP-19604 Aux Id: PR-9574

      • Removed the default values for SCTP send (sndbuf) and receive (recbuf) buffers.

        Own Id: OTP-19627 Aux Id: OTP-19576, GH-9722

      Improvements and New Features

      • application:load/1 slows down as the number of directories in the code path increases because the call to code:where_is_file/1 for the '.app' file must scan each directory for the app.

        code_server maintains a cache of the contents of directories in the path. Re-using that cache when searching for '.app' files in application:load/1 may improve its runtime, especially when loading multiple applications.

        Own Id: OTP-19194 Aux Id: PR-8078

      • The Erlang SSH daemon now uses the same backend to handle multiline functionality as the Erlang shell.

        Own Id: OTP-19226 Aux Id: PR-8805

      • Added support for SIGWINCH, SIGCONT, and SIGINFO signals to os:set_signal/2 where available.

        Own Id: OTP-19278 Aux Id: PR-8887, PR-8938

      • Add net_kernel:allowed/0, it returns a list of nodes that are explicitly allowed to connect to the node by calling -net_kernel:allow/1

        Own Id: OTP-19287 Aux Id: PR-8207

      • Documentation chunks (EEP-48) has been updated to include the following reserved metadata fields: behaviours, group, source_path, and source_annos. The compiler has also been updated to emit this metadata. See the EEP-48 documentation for more details.

        Own Id: OTP-19306 Aux Id: PR-8945, PR-8975

      • The erpc:call/3, erpc:call/5, erpc:multicall/3, and erpc:multicall/5 functions now also accept an option map as last argument containing the timeout and always_spawn options. The always_spawn option can be used in order to ensure that the call operation will use a newly spawned process when executing the remote call.

        Own Id: OTP-19343 Aux Id: PR-8642

      • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

        All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

        -type meter() :: integer().
        --type foot() :: integer().

        Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

        -nominal meter() :: integer().
        --nominal foot() :: integer().

        More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

        Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

        Own Id: OTP-19364 Aux Id: PR-9079

      • Improved open debug for gen_tcp_socket (connect and listen) and gen_udp_socket (open).

        Own Id: OTP-19386

      • io:standard_error/0 has been updated to write via a NIF API instead of a port. This allows it to access the dirty-scheduler pool and make sure that writes have been written to the OSs stderr when io:format/3 and equivalent return.

        Own Id: OTP-19401 Aux Id: PR-9116

      • Added the option exception_on_failure to os:cmd/2 to make os:cmd/2 raise an exception if the command fails to execute.

        Own Id: OTP-19404 Aux Id: PR-9082

      • A socket option {otp,select_read} has been added that enables keeping a socket in the VM select/poll set between calls to recv functions.

        This increases throughput by reducing the number of calls to said functions.

        Own Id: OTP-19451 Aux Id: PR-9344

      • Add a configure chapter to the socket usage guide

        Own Id: OTP-19522 Aux Id: PR-9508

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      • Increase the default inet-driver buffer size(s). Also introduce kernel parameters for UDP and SCTP to change the sizes when creating (those) sockets.

        Own Id: OTP-19576

      • An experimental API for a native debugger has been added. The main components are the following:

        • A new compiler option beam_debug_info for the Erlang compiler. When given, most optimizations are disabled and debug information suitable for the native debugger are added to generated BEAM files.

        • A new +D emulator flag. When given, the VM becomes "debuggable", which means that when modules that been compiled with the beam_debug_info option are loaded, the code is instrumented so that one can enable and disable breakpoints on executable lines.

        • An experimental erl_debugger module with a new debugging API. Essentially, it allows a single, local, process to be registered as the "debugger" process for the node. This process is the one that will receive messages notifying that a process hit a breakpoint. This way, the front-end implementation of a debugger (such as edb from WhatApp) can be decoupled from OTP.

        • The erl_debugger module also exposes new BIFs to inspect X and Y registers of a suspended process. Together with new code-information BIFs, this let's a debugger show the values of variables in scope for a suspended process.

        Own Id: OTP-19609 Aux Id: PR-8670, PR-9334, PR-9604

      Kernel 10.2.7.4

      Fixed Bugs and Malfunctions

      • Before this patch, the Erlang/OTP built-in DNS resolver (inet_res) used a sequential, process-global 16-bit transaction ID for UDP queries and did not implement source port randomization. Response validation relied almost entirely on this ID. Together, this made DNS cache poisoning practical for an attacker who can observe one query or predict the next ID. The design conflicted with RFC 5452 recommendations for mitigating forged DNS answers.

        inet_res is intended for use in trusted network environments and with trusted recursive resolvers. Earlier documentation did not clearly state this deployment assumption, which could lead users to deploy the resolver in environments where faked DNS responses are possible.

        Therefore, the documentation is been updated to clarify that inet_res should only be used in trusted networks and with trusted recursive resolvers.

        The implementation is also improved to use strong random DNS transaction IDs and source ports for every DNS transaction. This should give ample protection against brute forcing fake DNS replies, known as DNS cache poisoning, but it still does not protect against, for example, an adversary in the path of the DNS transaction that can observe the random values before faking malicious replies, an attack known as DNS spoofing.

        For randomization to happen, the Crypto application has to be loaded, which most probably already should be the case for an Erlang node in an exposed network.

        If performance should become an issue, for applications within safe network environments, the previous light weight behaviour can be configured by setting the resolver option random to false.

        Own Id: OTP-20037 Aux Id: CVE-2026-28810, PR-10864

      Kernel 10.2.7.3

      Improvements and New Features

      Kernel 10.2.7.2

      Fixed Bugs and Malfunctions

      • socket:sendv/3 with 'nowait' sometimes return 'completion' without 'CompletionInfo' (Windows only).

        Own Id: OTP-19661

      • socket:accept can return unexpected 'select_sent'.

        Own Id: OTP-19684 Aux Id: ERIERL-1242

      • net_kernel could be blocked for a very long time when selecting distribution module for a connection if the DNS service was slow. This prevented any new connections to be set up during that time.

        Own Id: OTP-19702 Aux Id: ERIERL-1241, PR-10029

      Improvements and New Features

      • Improved documentation of CompletionStatus for asynchronous (nowait) socket operations.

        Own Id: OTP-19670 Aux Id: PR-9930

      Kernel 10.2.7.1

      Fixed Bugs and Malfunctions

      • A remote shell can now exit by closing the input stream, without terminating the remote node.

        Own Id: OTP-19667 Aux Id: PR-9912

      Improvements and New Features

      • Document default buffer sizes

        Own Id: OTP-19640 Aux Id: GH-9722

      Kernel 10.2.7

      Fixed Bugs and Malfunctions

      • With this change, disk_log will not crash when using chunk_step/3 after log size was decreased.

        Own Id: OTP-19605 Aux Id: GH-9720, PR-9765

      • With this change, disk_log will not run into infinite loop when using chunk/2,3 after log size was decreased.

        Own Id: OTP-19608 Aux Id: GH-9707, PR-9767

      Kernel 10.2.6

      Fixed Bugs and Malfunctions

      • Fixed bug in call_memory tracing that could cause wildly incorrect reported memory values. Bug exists since OTP 27.1.

        Also fixed return type spec of trace:info/3.

        Own Id: OTP-19581 Aux Id: ERIERL-1219, PR-9706

      Kernel 10.2.5

      Fixed Bugs and Malfunctions

      • On Windows, using socket:sendv, a large IOV (size > MAX), the tail was not sent.

        Own Id: OTP-19482

      • gen_tcp connect with a sockaddr with loopback address failed.

        Own Id: OTP-19560 Aux Id: GH-9541

      • Remove debug printouts from gen_tcp_socket

        Own Id: OTP-19564

      Kernel 10.2.4

      Fixed Bugs and Malfunctions

      Kernel 10.2.3

      Fixed Bugs and Malfunctions

      • Clarify inet:setopts documentation

        Own Id: OTP-19416 Aux Id: PR-9248

      • Fix bug where log printouts would go missing when application_controller is stopping while log messages are being sent.

        This bug was introduced by OTP-19078 in Erlang/OTP 26.2.5.

        Own Id: OTP-19418 Aux Id: GH-9163, PR-9274

      • Fixes a bug in the socket type spec, which caused Dialyzer to reject some valid programs.

        Own Id: OTP-19429 Aux Id: PR-9295, PR-9379

      Kernel 10.2.2

      Fixed Bugs and Malfunctions

      • Fixed a couple of bugs that could make global's internal state inconsistent when a connection was reconnected.

        Own Id: OTP-19381 Aux Id: PR-9377, GH-9112, GH-9117

      Kernel 10.2.1

      Fixed Bugs and Malfunctions

      • Fix the default group_leader to reply {error,request} on invalid I/O requests instead of crashing.

        This bug was introduced in Erlang/OTP 27.2.

        Own Id: OTP-19444 Aux Id: GH-9237, PR-9318

      Kernel 10.2

      Fixed Bugs and Malfunctions

      • gen_sctp:peeloff/2 has been fixed to inherit socket options to the peeled off socket more like gen_tcp:accept/1, for example the options tos or tclass.

        When setting SCTP options that are unsupported on the platform, some should be silently ignored, but a bug caused the option parsing to derail so the options after could bail out and cause an error instead. This has been fixed.

        Own Id: OTP-19225 Aux Id: PR-8789

      • Made it possible to expand help text displayed by pressing ^[h by pressing ^[h again.

        Own Id: OTP-19260 Aux Id: PR-8884

      • inet:getifaddrs/0,1 is improved when using +net_kernel:allow/1

        Own Id: OTP-19287 Aux Id: PR-8207

      • Documentation chunks (EEP-48) has been updated to include the following reserved metadata fields: behaviours, group, source_path, and source_annos. The compiler has also been updated to emit this metadata. See the EEP-48 documentation for more details.

        Own Id: OTP-19306 Aux Id: PR-8945, PR-8975

      • The erpc:call/3, erpc:call/5, erpc:multicall/3, and erpc:multicall/5 functions now also accept an option map as last argument containing the timeout and always_spawn options. The always_spawn option can be used in order to ensure that the call operation will use a newly spawned process when executing the remote call.

        Own Id: OTP-19343 Aux Id: PR-8642

      • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

        All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

        -type meter() :: integer().
        +-type foot() :: integer().

        Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

        -nominal meter() :: integer().
        +-nominal foot() :: integer().

        More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

        Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

        Own Id: OTP-19364 Aux Id: PR-9079

      • Improved open debug for gen_tcp_socket (connect and listen) and gen_udp_socket (open).

        Own Id: OTP-19386

      • io:standard_error/0 has been updated to write via a NIF API instead of a port. This allows it to access the dirty-scheduler pool and make sure that writes have been written to the OSs stderr when io:format/3 and equivalent return.

        Own Id: OTP-19401 Aux Id: PR-9116

      • Added the option exception_on_failure to os:cmd/2 to make os:cmd/2 raise an exception if the command fails to execute.

        Own Id: OTP-19404 Aux Id: PR-9082

      • A socket option {otp,select_read} has been added that enables keeping a socket in the VM select/poll set between calls to recv functions.

        This increases throughput by reducing the number of calls to said functions.

        Own Id: OTP-19451 Aux Id: PR-9344

      • Add a configure chapter to the socket usage guide

        Own Id: OTP-19522 Aux Id: PR-9508

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      • Increase the default inet-driver buffer size(s). Also introduce kernel parameters for UDP and SCTP to change the sizes when creating (those) sockets.

        Own Id: OTP-19576

      • An experimental API for a native debugger has been added. The main components are the following:

        • A new compiler option beam_debug_info for the Erlang compiler. When given, most optimizations are disabled and debug information suitable for the native debugger are added to generated BEAM files.

        • A new +D emulator flag. When given, the VM becomes "debuggable", which means that when modules that been compiled with the beam_debug_info option are loaded, the code is instrumented so that one can enable and disable breakpoints on executable lines.

        • An experimental erl_debugger module with a new debugging API. Essentially, it allows a single, local, process to be registered as the "debugger" process for the node. This process is the one that will receive messages notifying that a process hit a breakpoint. This way, the front-end implementation of a debugger (such as edb from WhatApp) can be decoupled from OTP.

        • The erl_debugger module also exposes new BIFs to inspect X and Y registers of a suspended process. Together with new code-information BIFs, this let's a debugger show the values of variables in scope for a suspended process.

        Own Id: OTP-19609 Aux Id: PR-8670, PR-9334, PR-9604

      Kernel 10.2.7.4

      Fixed Bugs and Malfunctions

      • Before this patch, the Erlang/OTP built-in DNS resolver (inet_res) used a sequential, process-global 16-bit transaction ID for UDP queries and did not implement source port randomization. Response validation relied almost entirely on this ID. Together, this made DNS cache poisoning practical for an attacker who can observe one query or predict the next ID. The design conflicted with RFC 5452 recommendations for mitigating forged DNS answers.

        inet_res is intended for use in trusted network environments and with trusted recursive resolvers. Earlier documentation did not clearly state this deployment assumption, which could lead users to deploy the resolver in environments where faked DNS responses are possible.

        Therefore, the documentation is been updated to clarify that inet_res should only be used in trusted networks and with trusted recursive resolvers.

        The implementation is also improved to use strong random DNS transaction IDs and source ports for every DNS transaction. This should give ample protection against brute forcing fake DNS replies, known as DNS cache poisoning, but it still does not protect against, for example, an adversary in the path of the DNS transaction that can observe the random values before faking malicious replies, an attack known as DNS spoofing.

        For randomization to happen, the Crypto application has to be loaded, which most probably already should be the case for an Erlang node in an exposed network.

        If performance should become an issue, for applications within safe network environments, the previous light weight behaviour can be configured by setting the resolver option random to false.

        Own Id: OTP-20037 Aux Id: CVE-2026-28810, PR-10864

      Kernel 10.2.7.3

      Improvements and New Features

      Kernel 10.2.7.2

      Fixed Bugs and Malfunctions

      • socket:sendv/3 with 'nowait' sometimes return 'completion' without 'CompletionInfo' (Windows only).

        Own Id: OTP-19661

      • socket:accept can return unexpected 'select_sent'.

        Own Id: OTP-19684 Aux Id: ERIERL-1242

      • net_kernel could be blocked for a very long time when selecting distribution module for a connection if the DNS service was slow. This prevented any new connections to be set up during that time.

        Own Id: OTP-19702 Aux Id: ERIERL-1241, PR-10029

      Improvements and New Features

      • Improved documentation of CompletionStatus for asynchronous (nowait) socket operations.

        Own Id: OTP-19670 Aux Id: PR-9930

      Kernel 10.2.7.1

      Fixed Bugs and Malfunctions

      • A remote shell can now exit by closing the input stream, without terminating the remote node.

        Own Id: OTP-19667 Aux Id: PR-9912

      Improvements and New Features

      • Document default buffer sizes

        Own Id: OTP-19640 Aux Id: GH-9722

      Kernel 10.2.7

      Fixed Bugs and Malfunctions

      • With this change, disk_log will not crash when using chunk_step/3 after log size was decreased.

        Own Id: OTP-19605 Aux Id: GH-9720, PR-9765

      • With this change, disk_log will not run into infinite loop when using chunk/2,3 after log size was decreased.

        Own Id: OTP-19608 Aux Id: GH-9707, PR-9767

      Kernel 10.2.6

      Fixed Bugs and Malfunctions

      • Fixed bug in call_memory tracing that could cause wildly incorrect reported memory values. Bug exists since OTP 27.1.

        Also fixed return type spec of trace:info/3.

        Own Id: OTP-19581 Aux Id: ERIERL-1219, PR-9706

      Kernel 10.2.5

      Fixed Bugs and Malfunctions

      • On Windows, using socket:sendv, a large IOV (size > MAX), the tail was not sent.

        Own Id: OTP-19482

      • gen_tcp connect with a sockaddr with loopback address failed.

        Own Id: OTP-19560 Aux Id: GH-9541

      • Remove debug printouts from gen_tcp_socket

        Own Id: OTP-19564

      Kernel 10.2.4

      Fixed Bugs and Malfunctions

      Kernel 10.2.3

      Fixed Bugs and Malfunctions

      • Clarify inet:setopts documentation

        Own Id: OTP-19416 Aux Id: PR-9248

      • Fix bug where log printouts would go missing when application_controller is stopping while log messages are being sent.

        This bug was introduced by OTP-19078 in Erlang/OTP 26.2.5.

        Own Id: OTP-19418 Aux Id: GH-9163, PR-9274

      • Fixes a bug in the socket type spec, which caused Dialyzer to reject some valid programs.

        Own Id: OTP-19429 Aux Id: PR-9295, PR-9379

      Kernel 10.2.2

      Fixed Bugs and Malfunctions

      • Fixed a couple of bugs that could make global's internal state inconsistent when a connection was reconnected.

        Own Id: OTP-19381 Aux Id: PR-9377, GH-9112, GH-9117

      Kernel 10.2.1

      Fixed Bugs and Malfunctions

      • Fix the default group_leader to reply {error,request} on invalid I/O requests instead of crashing.

        This bug was introduced in Erlang/OTP 27.2.

        Own Id: OTP-19444 Aux Id: GH-9237, PR-9318

      Kernel 10.2

      Fixed Bugs and Malfunctions

      • gen_sctp:peeloff/2 has been fixed to inherit socket options to the peeled off socket more like gen_tcp:accept/1, for example the options tos or tclass.

        When setting SCTP options that are unsupported on the platform, some should be silently ignored, but a bug caused the option parsing to derail so the options after could bail out and cause an error instead. This has been fixed.

        Own Id: OTP-19225 Aux Id: PR-8789

      • Made it possible to expand help text displayed by pressing ^[h by pressing ^[h again.

        Own Id: OTP-19260 Aux Id: PR-8884

      • inet:getifaddrs/0,1 is improved when using inet_backend = socket.

        Own Id: OTP-19264

      • Fixed logger:report/0 to mandate at least one element in the report. This fixes an issue with overlapping spec domains in all logger functions that use logger:report/0.

        Own Id: OTP-19302 Aux Id: PR-8959

      • Fixed deadlock on code_server. Multiple calls loading the same module with an on_load function loading call would create a deadlock.

        Own Id: OTP-19305 Aux Id: PR-8744, GH-7466, GH-8510

      Improvements and New Features

      • The Kernel application now recognizes the epmd_module and erl_epmd_listen_port parameters, similar to -kernel:connect_all.

        Own Id: OTP-19253 Aux Id: PR-8671

      • The inetrc kernel argument will now tolerate atoms again to improve compatibility with old configurations that relied on atoms working by accident.

        The expected type always was, and still remains, a string.

        Own Id: OTP-19280 Aux Id: GH-8899, PR-8902

      • The file:io_device/0 type has been updated to clearly show the difference between a raw and cooked IoDevice.

        Own Id: OTP-19301 Aux Id: PR-8956

      • Erlang/OTP type specifications has been updated to eliminate overlapping domains.

        Own Id: OTP-19310 Aux Id: GH-8810, GH-8821, PR-8986

      • Added the kernel parameter os_cmd_shell that controls which shell should be used by os:cmd/1.

        Own Id: OTP-19342 Aux Id: PR-8972

      • Added logging support to io:user/0, io:standard_io/0 and io:standard_error/0. See io:setopts/2 for more details.

        Own Id: OTP-19372 Aux Id: PR-8947

      Kernel 10.1.2

      Fixed Bugs and Malfunctions

    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/pg.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1156)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/pg.html 2026-08-21 04:00:24.688329034 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/pg.html 2026-08-21 04:00:24.688329034 +0000 @@ -829,7 +829,7 @@

    Subscribes the caller to updates from the specified scope.

    Returns content of the entire scope and a reference to match the upcoming notifications.

    Whenever any group membership changes, an update message is sent to the -subscriber:

    {Ref, join, Group, [JoinPid1, JoinPid2]}
    {Ref, leave, Group, [LeavePid1]}
    +subscriber:

    {Ref, join, Group, [JoinPid1, JoinPid2]}
    {Ref, leave, Group, [LeavePid1]}
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/rpc.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (954)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/rpc.html 2026-08-21 04:00:24.719329236 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/rpc.html 2026-08-21 04:00:24.718329229 +0000 @@ -1043,10 +1043,10 @@ return values, or {badrpc, Reason} for failing calls. Timeout is a time (integer) in milliseconds, or infinity.

    The following example is useful when new object code is to be loaded on all nodes in the network, and indicates some side effects that RPCs can produce:

    %% Find object code for module Mod
    -{Mod, Bin, File} = code:get_object_code(Mod),
    +{Mod, Bin, File} = code:get_object_code(Mod),
     
     %% and load it on all nodes including this one
    -{ResL, _} = rpc:multicall(code, load_binary, [Mod, File, Bin]),
    +{ResL, _} = rpc:multicall(code, load_binary, [Mod, File, Bin]),
     
     %% and then maybe check the ResL list.

    Note

    If you want the ability to distinguish between results, you may want to consider using the erpc:multicall() function from the /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/seq_trace.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (839)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/seq_trace.html 2026-08-21 04:00:24.745329405 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/seq_trace.html 2026-08-21 04:00:24.746329411 +0000 @@ -100,9 +100,9 @@ how it can be used, see section Sequential Tracing.

    seq_trace provides functions that control all aspects of sequential tracing. There are functions for activation, deactivation, inspection, and for collection of the trace output.

    Trace Messages Sent to the System Tracer

    The format of the messages is one of the following, depending on if flag -timestamp of the trace token is set to true or false:

    {seq_trace, Label, SeqTraceInfo, TimeStamp}

    or

    {seq_trace, Label, SeqTraceInfo}

    Where:

    Label = int()
    -TimeStamp = {Seconds, Milliseconds, Microseconds}
    -  Seconds = Milliseconds = Microseconds = int()

    SeqTraceInfo can have the following formats:

    • {send, Serial, From, To, Message} - Used when a process From with its +timestamp of the trace token is set to true or false:

      {seq_trace, Label, SeqTraceInfo, TimeStamp}

      or

      {seq_trace, Label, SeqTraceInfo}

      Where:

      Label = int()
      +TimeStamp = {Seconds, Milliseconds, Microseconds}
      +  Seconds = Milliseconds = Microseconds = int()

      SeqTraceInfo can have the following formats:

      • {send, Serial, From, To, Message} - Used when a process From with its trace token flag send set to true has sent information. To may be a process identifier, a registered name on a node represented as {NameAtom, NodeAtom}, or a node name represented as an atom. From may be a @@ -198,68 +198,68 @@ C-nodes built with Erl_Interface too. A C-node built with Erl_Interface only maintains one trace token, which means that the C-node appears as one process from the sequential tracing point of view.

        Example of Use

        This example gives a rough idea of how the new primitives can be used and what -kind of output it produces.

        Assume that you have an initiating process with Pid == <0.30.0> like this:

        -module(seqex).
        --compile(export_all).
        +kind of output it produces.

        Assume that you have an initiating process with Pid == <0.30.0> like this:

        -module(seqex).
        +-compile(export_all).
         
        -loop(Port) ->
        +loop(Port) ->
             receive
        -        {Port,Message} ->
        -            seq_trace:set_token(label,17),
        -            seq_trace:set_token('receive',true),
        -            seq_trace:set_token(print,true),
        -            seq_trace:print(17,"**** Trace Started ****"),
        -            call_server ! {self(),the_message};
        -        {ack,Ack} ->
        +        {Port,Message} ->
        +            seq_trace:set_token(label,17),
        +            seq_trace:set_token('receive',true),
        +            seq_trace:set_token(print,true),
        +            seq_trace:print(17,"**** Trace Started ****"),
        +            call_server ! {self(),the_message};
        +        {ack,Ack} ->
                     ok
             end,
        -    loop(Port).

        And a registered process call_server with Pid == <0.31.0> like this:

        loop() ->
        +    loop(Port).

        And a registered process call_server with Pid == <0.31.0> like this:

        loop() ->
             receive
        -        {PortController,Message} ->
        -            Ack = {received, Message},
        -            seq_trace:print(17,"We are here now"),
        -            PortController ! {ack,Ack}
        +        {PortController,Message} ->
        +            Ack = {received, Message},
        +            seq_trace:print(17,"We are here now"),
        +            PortController ! {ack,Ack}
             end,
        -    loop().

        A possible output from the system's sequential_tracer can be like this:

        17:<0.30.0> Info {0,1} WITH
        +    loop().

        A possible output from the system's sequential_tracer can be like this:

        17:<0.30.0> Info {0,1} WITH
         "**** Trace Started ****"
        -17:<0.31.0> Received {0,2} FROM <0.30.0> WITH
        -{<0.30.0>,the_message}
        -17:<0.31.0> Info {2,3} WITH
        +17:<0.31.0> Received {0,2} FROM <0.30.0> WITH
        +{<0.30.0>,the_message}
        +17:<0.31.0> Info {2,3} WITH
         "We are here now"
        -17:<0.30.0> Received {2,4} FROM <0.31.0> WITH
        -{ack,{received,the_message}}

        The implementation of a system tracer process that produces this printout can -look like this:

        tracer() ->
        +17:<0.30.0> Received {2,4} FROM <0.31.0> WITH
        +{ack,{received,the_message}}

        The implementation of a system tracer process that produces this printout can +look like this:

        tracer() ->
             receive
        -        {seq_trace,Label,TraceInfo} ->
        -           print_trace(Label,TraceInfo,false);
        -        {seq_trace,Label,TraceInfo,Ts} ->
        -           print_trace(Label,TraceInfo,Ts);
        +        {seq_trace,Label,TraceInfo} ->
        +           print_trace(Label,TraceInfo,false);
        +        {seq_trace,Label,TraceInfo,Ts} ->
        +           print_trace(Label,TraceInfo,Ts);
                 _Other -> ignore
             end,
        -    tracer().
        +    tracer().
         
        -print_trace(Label,TraceInfo,false) ->
        -    io:format("~p:",[Label]),
        -    print_trace(TraceInfo);
        -print_trace(Label,TraceInfo,Ts) ->
        -    io:format("~p ~p:",[Label,Ts]),
        -    print_trace(TraceInfo).
        -
        -print_trace({print,Serial,From,_,Info}) ->
        -    io:format("~p Info ~p WITH~n~p~n", [From,Serial,Info]);
        -print_trace({'receive',Serial,From,To,Message}) ->
        -    io:format("~p Received ~p FROM ~p WITH~n~p~n",
        -              [To,Serial,From,Message]);
        -print_trace({send,Serial,From,To,Message}) ->
        -    io:format("~p Sent ~p TO ~p WITH~n~p~n",
        -              [From,Serial,To,Message]).

        The code that creates a process that runs this tracer function and sets that -process as the system tracer can look like this:

        start() ->
        -    Pid = spawn(?MODULE,tracer,[]),
        -    seq_trace:set_system_tracer(Pid), % set Pid as the system tracer
        -    ok.

        With a function like test/0, the whole example can be started:

        test() ->
        -    P = spawn(?MODULE, loop, [port]),
        -    register(call_server, spawn(?MODULE, loop, [])),
        -    start(),
        -    P ! {port,message}.
        +
        print_trace(Label,TraceInfo,false) -> + io:format("~p:",[Label]), + print_trace(TraceInfo); +print_trace(Label,TraceInfo,Ts) -> + io:format("~p ~p:",[Label,Ts]), + print_trace(TraceInfo). + +print_trace({print,Serial,From,_,Info}) -> + io:format("~p Info ~p WITH~n~p~n", [From,Serial,Info]); +print_trace({'receive',Serial,From,To,Message}) -> + io:format("~p Received ~p FROM ~p WITH~n~p~n", + [To,Serial,From,Message]); +print_trace({send,Serial,From,To,Message}) -> + io:format("~p Sent ~p TO ~p WITH~n~p~n", + [From,Serial,To,Message]).

        The code that creates a process that runs this tracer function and sets that +process as the system tracer can look like this:

        start() ->
        +    Pid = spawn(?MODULE,tracer,[]),
        +    seq_trace:set_system_tracer(Pid), % set Pid as the system tracer
        +    ok.

        With a function like test/0, the whole example can be started:

        test() ->
        +    P = spawn(?MODULE, loop, [port]),
        +    register(call_server, spawn(?MODULE, loop, [])),
        +    start(),
        +    P ! {port,message}.
    @@ -848,11 +848,11 @@ tracing is disabled, otherwise Token should be an Erlang term returned from get_token/0 or set_token/1. set_token/1 can be used to temporarily exclude message passing from the trace by setting the -trace token to empty like this:

    OldToken = seq_trace:set_token([]), % set to empty and save
    +trace token to empty like this:

    OldToken = seq_trace:set_token([]), % set to empty and save
                                         % old value
     % do something that should not be part of the trace
    -io:format("Exclude the signalling caused by this~n"),
    -seq_trace:set_token(OldToken), % activate the trace token again
    +io:format("Exclude the signalling caused by this~n"),
    +seq_trace:set_token(OldToken), % activate the trace token again
     ...

    Returns the previous value of the trace token.

    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/socket.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (959)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/socket.html 2026-08-21 04:00:24.825329926 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/socket.html 2026-08-21 04:00:24.826329932 +0000 @@ -153,8 +153,8 @@ to only scan the messages that arrive after the reference/0 is created. If the message queue is large this is a big optimization.

    It is not possible to have more than one operation in progress with the same reference/0.

    Repeating an Operation on a select Systems

    Onselect systems, if a call would be repeated before the select -message has been received it replaces the operation in progress:

        {select, {select_info, Handle}} = socket:accept(LSock, nowait),
    -    {ok, Socket} = socket:accept(LSock, 1000),
    +message has been received it replaces the operation in progress:

        {select, {select_info, Handle}} = socket:accept(LSock, nowait),
    +    {ok, Socket} = socket:accept(LSock, 1000),
         :

    Above, Handle is no longer valid once the second accept/2, call has been made (the first call is automatically canceled). After the second accept/2 call returns, the accept operation @@ -181,28 +181,28 @@ (select handle) API features could be considered no longer experimental.

  • In OTP 27.0, the Windows flavored (completion handle) -API features could be considered no longer experimental.
  • Examples

    client(SAddr, SPort) ->
    -   {ok, Sock} = socket:open(inet, stream, tcp),
    -   ok = socket:connect(Sock, #{family => inet,
    +API features could be considered no longer experimental.

    Examples

    client(SAddr, SPort) ->
    +   {ok, Sock} = socket:open(inet, stream, tcp),
    +   ok = socket:connect(Sock, #{family => inet,
                                    addr   => SAddr,
    -                               port   => SPort}),
    -   Msg = <<"hello">>,
    -   ok = socket:send(Sock, Msg),
    -   ok = socket:shutdown(Sock, write),
    -   {ok, Msg} = socket:recv(Sock),
    -   ok = socket:close(Sock).
    -
    -server(Addr, Port) ->
    -   {ok, LSock} = socket:open(inet, stream, tcp),
    -   ok = socket:bind(LSock, #{family => inet,
    +                               port   => SPort}),
    +   Msg = <<"hello">>,
    +   ok = socket:send(Sock, Msg),
    +   ok = socket:shutdown(Sock, write),
    +   {ok, Msg} = socket:recv(Sock),
    +   ok = socket:close(Sock).
    +
    +server(Addr, Port) ->
    +   {ok, LSock} = socket:open(inet, stream, tcp),
    +   ok = socket:bind(LSock, #{family => inet,
                                  port   => Port,
    -                             addr   => Addr}),
    -   ok = socket:listen(LSock),
    -   {ok, Sock} = socket:accept(LSock),
    -   {ok, Msg} = socket:recv(Sock),
    -   ok = socket:send(Sock, Msg),
    -   ok = socket:close(Sock),
    -   ok = socket:close(LSock).
    +
    addr => Addr}), + ok = socket:listen(LSock), + {ok, Sock} = socket:accept(LSock), + {ok, Msg} = socket:recv(Sock), + ok = socket:send(Sock, Msg), + ok = socket:close(Sock), + ok = socket:close(LSock).
    @@ -4849,7 +4849,7 @@ (since OTP 26.1).

    Result; a boolean/0.

  • tcp_info - Get miscellaneous TCP related information for a connected socket (since OTP 26.1).

    Result; a map/0 with information items as key-value pairs.

  • Note

    Not all requests are supported by all platforms. To see if a ioctl request is supported on the current platform:

          Request = nread,
    -      true = socket:is_supported(ioctl_requests, Request),
    +      true = socket:is_supported(ioctl_requests, Request),
           :
    @@ -5013,7 +5013,7 @@

    Check if a socket feature is supported.

    Returns true if supports/0 has a {Key1, true} tuple or a {Key1, list()} tuple in its returned list, -otherwise false (also for unknown keys).

    Example:

    true = socket:is_supported(local),
    +otherwise false (also for unknown keys).

    Example:

    true = socket:is_supported(local),
    @@ -5044,7 +5044,7 @@

    Check if a socket feature is supported.

    Returns true if supports(Key1) has a {Key2, true} tuple -in its returned list, otherwise false (also for unknown keys).

    Example:

    true = socket:is_supported(msg_flags, errqueue),
    +in its returned list, otherwise false (also for unknown keys).

    Example:

    true = socket:is_supported(msg_flags, errqueue),
    @@ -5141,7 +5141,7 @@

    Start a socket monitor.

    If the Socket doesn't exist or when later the monitor is triggered, a 'DOWN' message is sent to the process that called monitor/1 -with the following pattern:

    	    {'DOWN', MonitorRef, socket, Socket, Info}

    Info is the termination reason of the socket or nosock if +with the following pattern:

    	    {'DOWN', MonitorRef, socket, Socket, Info}

    Info is the termination reason of the socket or nosock if Socket did not exist when the monitor was started.

    Making several calls to socket:monitor/1 for the same Socket is not an error; each call creates an independent monitor instance.

    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/socket_usage.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (986)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/socket_usage.html 2026-08-21 04:00:24.864330180 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/socket_usage.html 2026-08-21 04:00:24.864330180 +0000 @@ -129,59 +129,59 @@ socket:sendv/3 with asynchronous (nowait) on completion systems (Windows).
    Observe that this is not an illustration how to write a asynchronous sendv function. Its just an example of what kind of messages and results that can be expected. The example below basically (re-) implements: -socket:sendv(Sock, IOV, infinity).

    completion_sendv(Sock, IOV) ->
    -    case socket:sendv(Sock, IOV, nowait) of
    +socket:sendv(Sock, IOV, infinity).

    completion_sendv(Sock, IOV) ->
    +    case socket:sendv(Sock, IOV, nowait) of
             ok -> % Complete success - We are done
                 ok;
    -        {completion, {CompletionInfo, RestIOV0}} ->
    +        {completion, {CompletionInfo, RestIOV0}} ->
                 %% Some of IOV was sent, but the rest, RestIOV0, was scheduled
    -            case completion_sendv_await_result(Sock,
    -                                               CompletionInfo, RestIOV0) of
    +            case completion_sendv_await_result(Sock,
    +                                               CompletionInfo, RestIOV0) of
                     ok -> % We done
                         ok;
    -                {ok, RestIOV} ->
    -                    completion_sendv(Sock, RestIOV);
    -                {error, Reason} ->
    -                    {error, {Reason, RestIOV0}}
    +                {ok, RestIOV} ->
    +                    completion_sendv(Sock, RestIOV);
    +                {error, Reason} ->
    +                    {error, {Reason, RestIOV0}}
                 end;
    -        {completion, CompletionInfo} ->
    +        {completion, CompletionInfo} ->
                 %% Nothing was sent, IOV was scheduled
    -            case completion_sendv_await_result(Sock,
    -                                               CompletionInfo, IOV) of
    +            case completion_sendv_await_result(Sock,
    +                                               CompletionInfo, IOV) of
                     ok -> % We done
                         ok;
    -                {ok, RestIOV} ->
    -                    completion_sendv(Sock, RestIOV);
    -                {error, _} = ERROR ->
    +                {ok, RestIOV} ->
    +                    completion_sendv(Sock, RestIOV);
    +                {error, _} = ERROR ->
                         ERROR
                 end;
    -        {error, {_Reason, _RestIOV}} = ERROR ->
    +        {error, {_Reason, _RestIOV}} = ERROR ->
                 %% Some part of the I/O vector was sent before an error occured
                 ERROR;
    -        {error, _} = ERROR ->
    +        {error, _} = ERROR ->
                 %% Note that 
                 ERROR
         end.
     
    -completion_sendv_await_result(Sock,
    -                              {completion_info, _, Handle},
    -                              IOV) ->
    +completion_sendv_await_result(Sock,
    +                              {completion_info, _, Handle},
    +                              IOV) ->
       receive
    -      {'$socket', Sock, abort, {Handle, Reason}} ->
    -          ?P("unexpected abort: "
    -             "~n   Reason: ~p", [Reason]),
    -          {error, {abort, Reason}};
    +      {'$socket', Sock, abort, {Handle, Reason}} ->
    +          ?P("unexpected abort: "
    +             "~n   Reason: ~p", [Reason]),
    +          {error, {abort, Reason}};
     
    -      {'$socket', Sock, completion, {Handle, {ok, Written}}} ->
    +      {'$socket', Sock, completion, {Handle, {ok, Written}}} ->
               %% Partial send; calculate rest I/O vector
    -          case socket:rest_iov(Written, IOV) of
    -              [] -> % We are done
    +          case socket:rest_iov(Written, IOV) of
    +              [] -> % We are done
                       ok;
                   RestIOV ->
    -                  {ok, RestIOV}
    +                  {ok, RestIOV}
               end;
     
    -      {'$socket', Sock, completion, {Handle, CompletionStatus}} ->
    +      {'$socket', Sock, completion, {Handle, CompletionStatus}} ->
               CompletionStatus
     
       end.

    Completion asynchronous recv

    This is a simple example function that illustrates how to use @@ -189,95 +189,95 @@ Observe that this is not an illustration how to write a asynchronous read function. Its just an example of what kind of messages and results that can be expected. The example below basically (re-) implements: -socket:recv(Sock, Sz).

    completion_recv(Sock, Sz) when (Sz > 0) ->
    -    completion_recv(Sock, Sz, []).
    +socket:recv(Sock, Sz).

    completion_recv(Sock, Sz) when (Sz > 0) ->
    +    completion_recv(Sock, Sz, []).
     
    -completion_recv(_Sock, 0, [Bin] = _Acc) ->
    -    {ok, Bin};
    -completion_recv(_Sock, 0, Acc) ->
    -    {ok, erlang:iolist_to_binary(lists:reverse(Acc))};
    -completion_recv(Sock, Sz, Acc) ->
    -    case socket:recv(Sock, Sz, nowait) of
    -        {ok, Bin} when (byte_size(Bin) =:= Sz) ->
    -            completion_recv(Sock, 0, [Bin|Acc]);
    -        {ok, Bin} ->
    -            completion_recv(Sock, Sz-byte_size(Bin), [Bin|Acc]);
    -
    -	{completion, CompletionInfo} ->
    -            case completion_recv_await_result(Sock, CompletionInfo) of
    -                {ok, Bin} ->
    -                    completion_recv(Sock, Sz-byte_size(Bin), [Bin|Acc]);
    -                {error, {_Reason, _Data}} = ERROR ->
    +completion_recv(_Sock, 0, [Bin] = _Acc) ->
    +    {ok, Bin};
    +completion_recv(_Sock, 0, Acc) ->
    +    {ok, erlang:iolist_to_binary(lists:reverse(Acc))};
    +completion_recv(Sock, Sz, Acc) ->
    +    case socket:recv(Sock, Sz, nowait) of
    +        {ok, Bin} when (byte_size(Bin) =:= Sz) ->
    +            completion_recv(Sock, 0, [Bin|Acc]);
    +        {ok, Bin} ->
    +            completion_recv(Sock, Sz-byte_size(Bin), [Bin|Acc]);
    +
    +	{completion, CompletionInfo} ->
    +            case completion_recv_await_result(Sock, CompletionInfo) of
    +                {ok, Bin} ->
    +                    completion_recv(Sock, Sz-byte_size(Bin), [Bin|Acc]);
    +                {error, {_Reason, _Data}} = ERROR ->
                         ERROR;
    -                {error, _Reason} = ERROR ->
    +                {error, _Reason} = ERROR ->
                         ERROR
     	    end;
     
    -	{error, {_Reason, _Data}} = ERROR ->
    +	{error, {_Reason, _Data}} = ERROR ->
     	    ERROR;
    -	{error, _Reason} = ERROR ->
    +	{error, _Reason} = ERROR ->
     	    ERROR
     
         end.
     
    -completion_recv_await_result(Sock,
    -                             {completion_info, _, Handle}) ->
    +completion_recv_await_result(Sock,
    +                             {completion_info, _, Handle}) ->
         receive
    -	{'$socket', Sock, abort, {Handle, Reason}} ->
    -	    {error, {abort, Reason}};
    +	{'$socket', Sock, abort, {Handle, Reason}} ->
    +	    {error, {abort, Reason}};
     
    -	{'$socket', Sock, completion, {Handle, {ok, _Bin} = OK}} ->
    +	{'$socket', Sock, completion, {Handle, {ok, _Bin} = OK}} ->
                 %% We "should" be done
     	    OK;
    -	{'$socket', Sock, completion, {Handle, {more, Bin}}} ->
    +	{'$socket', Sock, completion, {Handle, {more, Bin}}} ->
                 %% There is more to read
    -	    {ok, Bin};
    +	    {ok, Bin};
     
    -	{'$socket', Sock, completion, {Handle, CompletionStatus}} ->
    +	{'$socket', Sock, completion, {Handle, CompletionStatus}} ->
     	    CompletionStatus
     
         end.

    Echo server (and client)

    This example is intended to show how to create a simple (echo) server -(and client).

    -module(example).
    +(and client).

    -module(example).
     
    --export([client/2, client/3]).
    --export([server/0, server/1, server/2]).
    +-export([client/2, client/3]).
    +-export([server/0, server/1, server/2]).
     
     
     %% ======================================================================
     
     %% === Client ===
     
    -client(#{family := Family} = ServerSockAddr, Msg)
    -  when is_list(Msg) orelse is_binary(Msg) ->
    -    {ok, Sock} = socket:open(Family, stream, default),
    -    ok         = maybe_bind(Sock, Family),
    -    ok         = socket:connect(Sock, ServerSockAddr),
    -    client_exchange(Sock, Msg);
    +client(#{family := Family} = ServerSockAddr, Msg)
    +  when is_list(Msg) orelse is_binary(Msg) ->
    +    {ok, Sock} = socket:open(Family, stream, default),
    +    ok         = maybe_bind(Sock, Family),
    +    ok         = socket:connect(Sock, ServerSockAddr),
    +    client_exchange(Sock, Msg);
     
    -client(ServerPort, Msg)
    -  when is_integer(ServerPort) andalso (ServerPort > 0) ->
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/trace.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (5016))
    --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/trace.html	2026-08-21 04:00:24.905330447 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/trace.html	2026-08-21 04:00:24.904330440 +0000
    @@ -105,23 +105,23 @@
     messages. Several sessions can exist at the same time without interfering with
     each other. When a trace session is destroyed, all its trace settings are
     automatically cleaned up.

    Example:

    %% Create a tracer process that will receive the trace events
    -1> Tracer = spawn(fun F() -> receive M -> io:format("~p~n",[M]), F() end end).
    +1> Tracer = spawn(fun F() -> receive M -> io:format("~p~n",[M]), F() end end).
     <0.91.0>
     %% Create a session using the Tracer
    -2> Session = trace:session_create(my_session, Tracer, []).
    -{#Ref<0.1543805153.1548353537.92331>,{my_session, 0}}
    +2> Session = trace:session_create(my_session, Tracer, []).
    +{#Ref<0.1543805153.1548353537.92331>,{my_session, 0}}
     %% Setup call tracing on self()
    -3> trace:process(Session, self(), true, [call]).
    +3> trace:process(Session, self(), true, [call]).
     1
     %% Setup call tracing on lists:seq/2
    -4> trace:function(Session, {lists,seq,2}, [], []).
    +4> trace:function(Session, {lists,seq,2}, [], []).
     1
     %% Call the traced function
    -5> lists:seq(1, 10).
    -{trace,<0.89.0>,call,{lists,seq,[1,10]}} % The trace message
    -[1,2,3,4,5,6,7,8,9,10] % The return value
    +5> lists:seq(1, 10).
    +{trace,<0.89.0>,call,{lists,seq,[1,10]}} % The trace message
    +[1,2,3,4,5,6,7,8,9,10] % The return value
     %% Cleanup the trace session
    -6> trace:session_destroy(Session).
    +6> trace:session_destroy(Session).
     ok

    Node Local Tracing Only

    The functions in this module only operates on the local node. That is, both the traced processes/ports as well as the tracer process/port/module must all reside on the same local node as the call is made. To trace remote nodes use dbg or @@ -1415,9 +1415,9 @@ Match Specifications in Erlang in the User's Guide for the ERTS application.

  • true - Enable tracing for all received messages (to 'receive' traced processes). Any match specification is removed. This is the default.

  • false - Disable tracing for all received messages. Any match -specification is removed.

  • Argument FlagList must be [] for receive tracing.

    The return value is always 1.

    Examples:

    Only trace messages from a specific process Pid:

    > trace:recv(Session, [{[&#href_anchor"p">,Pid, '_'],[],[]}], []).
    -1

    Only trace messages matching {reply, _}:

    > trace:recv(Session, [{['_','_', {reply,'_'}],[],[]}], []).
    -1

    Only trace messages from other nodes:

    > trace:recv(Session, [{['$1', '_', '_'],[{'=/=','$1',{node}}],[]}], []).
    +specification is removed.

    Argument FlagList must be [] for receive tracing.

    The return value is always 1.

    Examples:

    Only trace messages from a specific process Pid:

    > trace:recv(Session, [{[&#href_anchor"p">,Pid, '_'],[],[]}], []).
    +1

    Only trace messages matching {reply, _}:

    > trace:recv(Session, [{['_','_', {reply,'_'}],[],[]}], []).
    +1

    Only trace messages from other nodes:

    > trace:recv(Session, [{['$1', '_', '_'],[{'=/=','$1',{node}}],[]}], []).
     1

    Note

    A match specification for 'receive' trace can use all guard and body functions except caller, is_seq_trace, get_seq_token, set_seq_token, enable_trace, disable_trace, trace, silent, and process_dump.

    Fails by raising an error exception with an error reason of:

    • badarg - If an argument is invalid.

    • system_limit - If a match specification passed as argument has excessive @@ -1468,10 +1468,10 @@ Match Specifications in Erlang in the User's Guide for the ERTS application.

    • true - Enable tracing for all sent messages (from send traced processes). Any match specification is removed.

    • false - Disable tracing for all sent messages. Any match specification -is removed.

    Argument FlagList must be [].

    The return value is always 1.

    Examples:

    Only trace messages to a specific process Pid:

    > trace:send(Session, [{[Pid, &#href_anchor"p" data-group-id="8105477857-4">],[],[]}], []).
    -1

    Only trace messages matching {reply, _}:

    > trace:send(Session, [{['_', {reply,'_'}],[],[]}], []).
    -1

    Only trace messages sent to the sender itself:

    > trace:send(Session, [{['$1', '_'],[{'=:=','$1',{self}}],[]}], []).
    -1

    Only trace messages sent to other nodes:

    > trace:send(Session, [{['$1', '_'],[{'=/=',{node,'$1'},{node}}],[]}], []).
    +is removed.

    Argument FlagList must be [].

    The return value is always 1.

    Examples:

    Only trace messages to a specific process Pid:

    > trace:send(Session, [{[Pid, &#href_anchor"p" data-group-id="8729336194-4">],[],[]}], []).
    +1

    Only trace messages matching {reply, _}:

    > trace:send(Session, [{['_', {reply,'_'}],[],[]}], []).
    +1

    Only trace messages sent to the sender itself:

    > trace:send(Session, [{['$1', '_'],[{'=:=','$1',{self}}],[]}], []).
    +1

    Only trace messages sent to other nodes:

    > trace:send(Session, [{['$1', '_'],[{'=/=',{node,'$1'},{node}}],[]}], []).
     1

    Note

    A match specification for send trace can use all guard and body functions except caller.

    Fails by raising an error exception with an error reason of:

    • badarg - If an argument is invalid.

    • system_limit - If a match specification passed as argument has excessive nesting which causes scheduler stack exhaustion for the scheduler that the /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> megaco - 4.8.3.1 - urn:uuid:37962a2f-3b63-e690-3108-5560a93a9dca + urn:uuid:a2ee2ea6-e4f6-0a0b-25cd-4035fe10a4d6 en - 2026-08-21T03:49:49Z + 2042-09-22T17:08:50Z /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_debug.xhtml differs (HTML document, ASCII text, with very long lines (1148)) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_debug.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_debug.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -34,12 +34,12 @@ can be expected by the different codecs provided by the megaco application.

      The measurement is done by iterating over the decode/encode function for approx 2 seconds per message and counting the number of decodes/encodes.

      Is best run by modifying the meas.sh.skel skeleton script provided by the tool.

      To run it manually do the following:

              % erl -pa <path-megaco-ebin-dir> -pa <path-to-meas-module-dir>
      -        Erlang (BEAM) emulator version 5.6 [source]
      +        Erlang (BEAM) emulator version 5.6 [source]
       
      -        Eshell V12.2  (abort with ^G)
      -        1> megaco_codec_meas:start().
      +        Eshell V12.2  (abort with ^G)
      +        1> megaco_codec_meas:start().
               ...
      -        2> halt().

      or to make it even easier, assuming a measure shall be done on all the codecs + 2> halt().

    or to make it even easier, assuming a measure shall be done on all the codecs (as above):

            % erl -noshell -pa <path-megaco-ebin-dir> \\
                   -pa <path-to-meas-module-dir> \\
                   -s megaco_codec_meas -s init stop

    When run as above (this will take some time), the measurement process is done @@ -61,10 +61,10 @@ value.

    Both these tools use the message package (time_test.msgs) provided with the tool(s), although it can run on any message package as long as it has the same structure.

    Message package file

    This is simply an erlang compatible text-file with the following structure: -{codec_name(), messages_list()}.

    codec_name() = pretty | compact | ber | per | erlang      (how the messages are encoded)
    -messages_list() = [{message_name(), message()}]
    -message_name() = atom()
    -message() = binary()

    The codec name is the name of the codec with which all messages in the +{codec_name(), messages_list()}.

    codec_name() = pretty | compact | ber | per | erlang      (how the messages are encoded)
    +messages_list() = [{message_name(), message()}]
    +message_name() = atom()
    +message() = binary()

    The codec name is the name of the codec with which all messages in the message_list() has been encoded.

    This file can be exported to a file structure by calling the export_messages function. This can be usefull if a measurement shall be done with an external tool. Exporting the /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_encode.xhtml differs (HTML document, ASCII text, with very long lines (783)) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_encode.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_encode.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -38,75 +38,75 @@ format using long keywords and an indentation style like the text examples in the Megaco/H.248 specification).

    Here follows an example of a text message to give a feeling of the difference between the pretty and compact versions of text messages. First the pretty, well -indented version with long keywords:

       MEGACO/1 [124.124.124.222]
    -   Transaction = 9998 {
    -           Context = - {
    -                   ServiceChange = ROOT {
    -                           Services {
    +indented version with long keywords:

       MEGACO/1 [124.124.124.222]
    +   Transaction = 9998 {
    +           Context = - {
    +                   ServiceChange = ROOT {
    +                           Services {
                                        Method = Restart,
                                        ServiceChangeAddress = 55555,
                                        Profile = ResGW/1,
                                        Reason = "901 Cold Boot"
    -                           }
    -                   }
    -           }
    -   }

    Then the compact version without indentation and with short keywords:

    
    +                           }
    +                   }
    +           }
    +   }

    Then the compact version without indentation and with short keywords:

    
        !/1 [124.124.124.222]
        T=9998{C=-{SC=ROOT{SV{MT=RS,AD=55555,PF=ResGW/1,RE="901 Cold Boot"}}}}

    And the programmers view of the same message. First a list of ActionRequest records are constructed and then it is sent with one of the send functions in -the API:

      Prof = #'ServiceChangeProfile'{profileName = "resgw", version = 1},
    -  Parm = #'ServiceChangeParm'{serviceChangeMethod  = restart,
    -                              serviceChangeAddress = {portNumber, 55555},
    +the API:

      Prof = #'ServiceChangeProfile'{profileName = "resgw", version = 1},
    +  Parm = #'ServiceChangeParm'{serviceChangeMethod  = restart,
    +                              serviceChangeAddress = {portNumber, 55555},
                                   serviceChangeReason  = "901 Cold Boot",
    -                              serviceChangeProfile = Prof},
    -  Req = #'ServiceChangeRequest'{terminationID = [?megaco_root_termination_id],
    -                                serviceChangeParms = Parm},
    -  Actions = [#'ActionRequest'{contextId = ?megaco_null_context_id,
    -                              commandRequests = {serviceChangeReq, Req}}],
    -  megaco:call(ConnHandle, Actions, Config).

    And finally a print-out of the entire internal form:

      {'MegacoMessage',
    +                              serviceChangeProfile = Prof},
    +  Req = #'ServiceChangeRequest'{terminationID = [?megaco_root_termination_id],
    +                                serviceChangeParms = Parm},
    +  Actions = [#'ActionRequest'{contextId = ?megaco_null_context_id,
    +                              commandRequests = {serviceChangeReq, Req}}],
    +  megaco:call(ConnHandle, Actions, Config).

    And finally a print-out of the entire internal form:

      {'MegacoMessage',
        asn1_NOVALUE,
    -   {'Message',
    +   {'Message',
         1,
    -    {ip4Address,{'IP4Address', [124,124,124,222], asn1_NOVALUE}},
    -    {transactions,
    -     [
    -      {transactionRequest,
    -       {'TransactionRequest',
    +    {ip4Address,{'IP4Address', [124,124,124,222], asn1_NOVALUE}},
    +    {transactions,
    +     [
    +      {transactionRequest,
    +       {'TransactionRequest',
              9998,
    -         [{'ActionRequest',
    +         [{'ActionRequest',
                0,
                asn1_NOVALUE,
                asn1_NOVALUE,
    -           [
    -            {'CommandRequest',
    -             {serviceChangeReq,
    -              {'ServiceChangeRequest',
    -               [
    -                {megaco_term_id, false, ["root"]}],
    -                {'ServiceChangeParm',
    +           [
    +            {'CommandRequest',
    +             {serviceChangeReq,
    +              {'ServiceChangeRequest',
    +               [
    +                {megaco_term_id, false, ["root"]}],
    +                {'ServiceChangeParm',
                      restart,
    -                 {portNumber, 55555},
    +                 {portNumber, 55555},
                      asn1_NOVALUE,
    -                 {'ServiceChangeProfile', "resgw", version = 1},
    +                 {'ServiceChangeProfile', "resgw", version = 1},
                      "901 MG Cold Boot",
                      asn1_NOVALUE,
                      asn1_NOVALUE,
                      asn1_NOVALUE
    -                }
    -              }
    -             },
    +                }
    +              }
    +             },
                  asn1_NOVALUE,
                  asn1_NOVALUE
    -            }
    -           ]
    -          }
    -         ]
    -       }
    -      }
    -     ]
    -    }
    -   }
    -  }

    The following encoding modules are provided:

    • megaco_pretty_text_encoder - encodes messages into pretty text format, decodes + } + ] + } + ] + } + } + ] + } + } + }

    The following encoding modules are provided:

    • megaco_pretty_text_encoder - encodes messages into pretty text format, decodes both pretty as well as compact text.
    • megaco_compact_text_encoder - encodes messages into compact text format, decodes both pretty as well as compact text.
    • megaco_binary_encoder - encode/decode ASN.1 BER messages. This encoder implements the fastest of the BER encoders/decoders. Recommended binary codec.
    • megaco_ber_encoder - encode/decode ASN.1 BER messages.
    • megaco_per_encoder - encode/decode ASN.1 PER messages. N.B. that this format /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_examples.xhtml differs (HTML document, ASCII text, with very long lines (558)) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_examples.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_examples.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -39,10 +39,10 @@ erl -pa ../../../megaco/ebin -s megaco_filter -s megaco megaco_simple_mg:start().

    or simply 'gmake mg'.

    If you "only" want to start a single MG which tries to connect an MG on a host named "baidarka", you may use one of these functions (instead of the -megaco_simple_mg:start/0 above):

          megaco_simple_mg:start_tcp_text("baidarka", []).
    -      megaco_simple_mg:start_tcp_binary("baidarka", []).
    -      megaco_simple_mg:start_udp_text("baidarka", []).
    -      megaco_simple_mg:start_udp_binary("baidarka", []).

    The -s megaco_filter option to erl implies, the event tracing mechanism to be +megaco_simple_mg:start/0 above):

          megaco_simple_mg:start_tcp_text("baidarka", []).
    +      megaco_simple_mg:start_tcp_binary("baidarka", []).
    +      megaco_simple_mg:start_udp_text("baidarka", []).
    +      megaco_simple_mg:start_udp_binary("baidarka", []).

    The -s megaco_filter option to erl implies, the event tracing mechanism to be enabled and an interactive sequence chart tool to be started. This may be quite useful in order to visualize how your MG interacts with the Megaco/H.248 protocol stack.

    The event traces may alternatively be directed to a file for later analyze. By /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_performance.xhtml differs (HTML document, ASCII text, with very long lines (3018)) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_performance.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_performance.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -42,19 +42,19 @@ built-in functions.

    The actual encoded messages have been collected in one directory per encoding type, containing one file per encoded message.

    Here follows an example of a text message to give a feeling of the difference between the pretty and compact versions of text messages. First the pretty -printed, well indented version with long keywords:

    MEGACO/1 [124.124.124.222]
    -  Transaction = 9998 {
    -    Context = - {
    -      ServiceChange = ROOT {
    -        Services {
    +printed, well indented version with long keywords:

    MEGACO/1 [124.124.124.222]
    +  Transaction = 9998 {
    +    Context = - {
    +      ServiceChange = ROOT {
    +        Services {
               Method = Restart,
               ServiceChangeAddress = 55555,
               Profile = ResGW/1,
               Reason = "901 MG Cold Boot"
    -        }
    -      }
    -    }
    -  }

    Then the compact text version without indentation and with short keywords:

    !/1 [124.124.124.222] T=9998{
    +        }
    +      }
    +    }
    +  }

    Then the compact text version without indentation and with short keywords:

    !/1 [124.124.124.222] T=9998{
       C=-{SC=ROOT{SV{MT=RS,AD=55555,PF=ResGW/1,RE="901 MG Cold Boot"}}}}

    Setup

    The measurements has been performed on a Dell Precision 5550 Laptop with a Intel(R) Core(TM) i7-10875H CPU @ 2.30GHz, with 40 GB memory and running Ubuntu 20.04 x86_64, kernel 5.4.0-91-generic. Software versions was open source OTP /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_user.xhtml differs (HTML document, ASCII text, with very long lines (1057)) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_user.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco_user.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -25,17 +25,17 @@

    Callback module for users of the Megaco application

    This module defines the callback behaviour of Megaco users. A megaco_user compliant callback module must export the following functions:

    The semantics of them and their exact signatures are explained below.

    The user_args configuration parameter which may be used to extend the argument list of the callback functions. For example, the handle_connect function takes -by default two arguments:

    handle_connect(Handle, Version)

    but if the user_args parameter is set to a longer list, such as +by default two arguments:

    handle_connect(Handle, Version)

    but if the user_args parameter is set to a longer list, such as [SomePid,SomeTableRef], the callback function is expected to have these (in -this case two) extra arguments last in the argument list:

    handle_connect(Handle, Version, SomePid, SomeTableRef)

    Note

    Must of the functions below has an optional Extra argument (e.g. +this case two) extra arguments last in the argument list:

    handle_connect(Handle, Version, SomePid, SomeTableRef)

    Note

    Must of the functions below has an optional Extra argument (e.g. handle_unexpected_trans/4). The functions which takes this argument will be called if and only if one of the functions receive_message/5 or process_received_message/5 was called -with the Extra argument different than ignore_extra.

    DATA TYPES

    action_request() = #'ActionRequest'{}
    -action_reply() = #'ActionReply'{}
    -error_desc() = #'ErrorDescriptor'{}
    -segment_no() = integer()
    conn_handle() = #megaco_conn_handle{}

    The record initially returned by megaco:connect/4,5. It identifies a "virtual" +with the Extra argument different than ignore_extra.

    DATA TYPES

    action_request() = #'ActionRequest'{}
    +action_reply() = #'ActionReply'{}
    +error_desc() = #'ErrorDescriptor'{}
    +segment_no() = integer()
    conn_handle() = #megaco_conn_handle{}

    The record initially returned by megaco:connect/4,5. It identifies a "virtual" connection and may be reused after a reconnect (disconnect + connect).

    protocol_version() = integer()

    Is the actual protocol version. In most cases the protocol version is retrieved from the processed message, but there are exceptions:

    In these cases, the ProtocolVersion default version is obtained from the static /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco.xhtml differs (HTML document, ASCII text, with very long lines (1060)) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.epub/OEBPS/megaco.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -3071,7 +3071,7 @@

    Utility function to produce a formated printout of the versions info generated by the versions1 and versions2 functions.

    The function print_version_info/0 uses the result of function version1/0 as -VersionInfo.

    Example:

               {ok, V} = megaco:versions1(), megaco:format_versions(V).
    +VersionInfo.

    Example:

               {ok, V} = megaco:versions1(), megaco:format_versions(V).
    /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1057)) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.html 2026-08-21 04:00:25.099331709 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco.html 2026-08-21 04:00:25.099331709 +0000 @@ -3154,7 +3154,7 @@

    Utility function to produce a formated printout of the versions info generated by the versions1 and versions2 functions.

    The function print_version_info/0 uses the result of function version1/0 as -VersionInfo.

    Example:

               {ok, V} = megaco:versions1(), megaco:format_versions(V).
    +VersionInfo.

    Example:

               {ok, V} = megaco:versions1(), megaco:format_versions(V).
    /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_debug.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1519)) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_debug.html 2026-08-21 04:00:25.118331833 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_debug.html 2026-08-21 04:00:25.118331833 +0000 @@ -106,12 +106,12 @@ can be expected by the different codecs provided by the megaco application.

    The measurement is done by iterating over the decode/encode function for approx 2 seconds per message and counting the number of decodes/encodes.

    Is best run by modifying the meas.sh.skel skeleton script provided by the tool.

    To run it manually do the following:

            % erl -pa <path-megaco-ebin-dir> -pa <path-to-meas-module-dir>
    -        Erlang (BEAM) emulator version 5.6 [source]
    +        Erlang (BEAM) emulator version 5.6 [source]
     
    -        Eshell V12.2  (abort with ^G)
    -        1> megaco_codec_meas:start().
    +        Eshell V12.2  (abort with ^G)
    +        1> megaco_codec_meas:start().
             ...
    -        2> halt().

    or to make it even easier, assuming a measure shall be done on all the codecs + 2> halt().

    or to make it even easier, assuming a measure shall be done on all the codecs (as above):

            % erl -noshell -pa <path-megaco-ebin-dir> \\
                   -pa <path-to-meas-module-dir> \\
                   -s megaco_codec_meas -s init stop

    When run as above (this will take some time), the measurement process is done @@ -133,10 +133,10 @@ value.

    Both these tools use the message package (time_test.msgs) provided with the tool(s), although it can run on any message package as long as it has the same structure.

    Message package file

    This is simply an erlang compatible text-file with the following structure: -{codec_name(), messages_list()}.

    codec_name() = pretty | compact | ber | per | erlang      (how the messages are encoded)
    -messages_list() = [{message_name(), message()}]
    -message_name() = atom()
    -message() = binary()

    The codec name is the name of the codec with which all messages in the +{codec_name(), messages_list()}.

    codec_name() = pretty | compact | ber | per | erlang      (how the messages are encoded)
    +messages_list() = [{message_name(), message()}]
    +message_name() = atom()
    +message() = binary()

    The codec name is the name of the codec with which all messages in the message_list() has been encoded.

    This file can be exported to a file structure by calling the export_messages function. This can be usefull if a measurement shall be done with an external tool. Exporting the /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_encode.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (783)) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_encode.html 2026-08-21 04:00:25.139331970 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_encode.html 2026-08-21 04:00:25.139331970 +0000 @@ -110,75 +110,75 @@ format using long keywords and an indentation style like the text examples in the Megaco/H.248 specification).

    Here follows an example of a text message to give a feeling of the difference between the pretty and compact versions of text messages. First the pretty, well -indented version with long keywords:

       MEGACO/1 [124.124.124.222]
    -   Transaction = 9998 {
    -           Context = - {
    -                   ServiceChange = ROOT {
    -                           Services {
    +indented version with long keywords:

       MEGACO/1 [124.124.124.222]
    +   Transaction = 9998 {
    +           Context = - {
    +                   ServiceChange = ROOT {
    +                           Services {
                                        Method = Restart,
                                        ServiceChangeAddress = 55555,
                                        Profile = ResGW/1,
                                        Reason = "901 Cold Boot"
    -                           }
    -                   }
    -           }
    -   }

    Then the compact version without indentation and with short keywords:

    
    +                           }
    +                   }
    +           }
    +   }

    Then the compact version without indentation and with short keywords:

    
        !/1 [124.124.124.222]
        T=9998{C=-{SC=ROOT{SV{MT=RS,AD=55555,PF=ResGW/1,RE="901 Cold Boot"}}}}

    And the programmers view of the same message. First a list of ActionRequest records are constructed and then it is sent with one of the send functions in -the API:

      Prof = #'ServiceChangeProfile'{profileName = "resgw", version = 1},
    -  Parm = #'ServiceChangeParm'{serviceChangeMethod  = restart,
    -                              serviceChangeAddress = {portNumber, 55555},
    +the API:

      Prof = #'ServiceChangeProfile'{profileName = "resgw", version = 1},
    +  Parm = #'ServiceChangeParm'{serviceChangeMethod  = restart,
    +                              serviceChangeAddress = {portNumber, 55555},
                                   serviceChangeReason  = "901 Cold Boot",
    -                              serviceChangeProfile = Prof},
    -  Req = #'ServiceChangeRequest'{terminationID = [?megaco_root_termination_id],
    -                                serviceChangeParms = Parm},
    -  Actions = [#'ActionRequest'{contextId = ?megaco_null_context_id,
    -                              commandRequests = {serviceChangeReq, Req}}],
    -  megaco:call(ConnHandle, Actions, Config).

    And finally a print-out of the entire internal form:

      {'MegacoMessage',
    +                              serviceChangeProfile = Prof},
    +  Req = #'ServiceChangeRequest'{terminationID = [?megaco_root_termination_id],
    +                                serviceChangeParms = Parm},
    +  Actions = [#'ActionRequest'{contextId = ?megaco_null_context_id,
    +                              commandRequests = {serviceChangeReq, Req}}],
    +  megaco:call(ConnHandle, Actions, Config).

    And finally a print-out of the entire internal form:

      {'MegacoMessage',
        asn1_NOVALUE,
    -   {'Message',
    +   {'Message',
         1,
    -    {ip4Address,{'IP4Address', [124,124,124,222], asn1_NOVALUE}},
    -    {transactions,
    -     [
    -      {transactionRequest,
    -       {'TransactionRequest',
    +    {ip4Address,{'IP4Address', [124,124,124,222], asn1_NOVALUE}},
    +    {transactions,
    +     [
    +      {transactionRequest,
    +       {'TransactionRequest',
              9998,
    -         [{'ActionRequest',
    +         [{'ActionRequest',
                0,
                asn1_NOVALUE,
                asn1_NOVALUE,
    -           [
    -            {'CommandRequest',
    -             {serviceChangeReq,
    -              {'ServiceChangeRequest',
    -               [
    -                {megaco_term_id, false, ["root"]}],
    -                {'ServiceChangeParm',
    +           [
    +            {'CommandRequest',
    +             {serviceChangeReq,
    +              {'ServiceChangeRequest',
    +               [
    +                {megaco_term_id, false, ["root"]}],
    +                {'ServiceChangeParm',
                      restart,
    -                 {portNumber, 55555},
    +                 {portNumber, 55555},
                      asn1_NOVALUE,
    -                 {'ServiceChangeProfile', "resgw", version = 1},
    +                 {'ServiceChangeProfile', "resgw", version = 1},
                      "901 MG Cold Boot",
                      asn1_NOVALUE,
                      asn1_NOVALUE,
                      asn1_NOVALUE
    -                }
    -              }
    -             },
    +                }
    +              }
    +             },
                  asn1_NOVALUE,
                  asn1_NOVALUE
    -            }
    -           ]
    -          }
    -         ]
    -       }
    -      }
    -     ]
    -    }
    -   }
    -  }

    The following encoding modules are provided:

    • megaco_pretty_text_encoder - encodes messages into pretty text format, decodes + } + ] + } + ] + } + } + ] + } + } + }

    The following encoding modules are provided:

    • megaco_pretty_text_encoder - encodes messages into pretty text format, decodes both pretty as well as compact text.
    • megaco_compact_text_encoder - encodes messages into compact text format, decodes both pretty as well as compact text.
    • megaco_binary_encoder - encode/decode ASN.1 BER messages. This encoder implements the fastest of the BER encoders/decoders. Recommended binary codec.
    • megaco_ber_encoder - encode/decode ASN.1 BER messages.
    • megaco_per_encoder - encode/decode ASN.1 PER messages. N.B. that this format /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_examples.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_examples.html 2026-08-21 04:00:25.157332087 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_examples.html 2026-08-21 04:00:25.157332087 +0000 @@ -111,10 +111,10 @@ erl -pa ../../../megaco/ebin -s megaco_filter -s megaco megaco_simple_mg:start().

    or simply 'gmake mg'.

    If you "only" want to start a single MG which tries to connect an MG on a host named "baidarka", you may use one of these functions (instead of the -megaco_simple_mg:start/0 above):

          megaco_simple_mg:start_tcp_text("baidarka", []).
    -      megaco_simple_mg:start_tcp_binary("baidarka", []).
    -      megaco_simple_mg:start_udp_text("baidarka", []).
    -      megaco_simple_mg:start_udp_binary("baidarka", []).

    The -s megaco_filter option to erl implies, the event tracing mechanism to be +megaco_simple_mg:start/0 above):

          megaco_simple_mg:start_tcp_text("baidarka", []).
    +      megaco_simple_mg:start_tcp_binary("baidarka", []).
    +      megaco_simple_mg:start_udp_text("baidarka", []).
    +      megaco_simple_mg:start_udp_binary("baidarka", []).

    The -s megaco_filter option to erl implies, the event tracing mechanism to be enabled and an interactive sequence chart tool to be started. This may be quite useful in order to visualize how your MG interacts with the Megaco/H.248 protocol stack.

    The event traces may alternatively be directed to a file for later analyze. By /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_performance.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (3158)) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_performance.html 2026-08-21 04:00:25.176332211 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_performance.html 2026-08-21 04:00:25.175332204 +0000 @@ -114,19 +114,19 @@ built-in functions.

    The actual encoded messages have been collected in one directory per encoding type, containing one file per encoded message.

    Here follows an example of a text message to give a feeling of the difference between the pretty and compact versions of text messages. First the pretty -printed, well indented version with long keywords:

    MEGACO/1 [124.124.124.222]
    -  Transaction = 9998 {
    -    Context = - {
    -      ServiceChange = ROOT {
    -        Services {
    +printed, well indented version with long keywords:

    MEGACO/1 [124.124.124.222]
    +  Transaction = 9998 {
    +    Context = - {
    +      ServiceChange = ROOT {
    +        Services {
               Method = Restart,
               ServiceChangeAddress = 55555,
               Profile = ResGW/1,
               Reason = "901 MG Cold Boot"
    -        }
    -      }
    -    }
    -  }

    Then the compact text version without indentation and with short keywords:

    !/1 [124.124.124.222] T=9998{
    +        }
    +      }
    +    }
    +  }

    Then the compact text version without indentation and with short keywords:

    !/1 [124.124.124.222] T=9998{
       C=-{SC=ROOT{SV{MT=RS,AD=55555,PF=ResGW/1,RE="901 MG Cold Boot"}}}}

    Setup

    The measurements has been performed on a Dell Precision 5550 Laptop with a Intel(R) Core(TM) i7-10875H CPU @ 2.30GHz, with 40 GB memory and running Ubuntu 20.04 x86_64, kernel 5.4.0-91-generic. Software versions was open source OTP /usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_user.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (934)) --- old//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_user.html 2026-08-21 04:00:25.203332386 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/megaco-4.8.3.1/doc/html/megaco_user.html 2026-08-21 04:00:25.203332386 +0000 @@ -96,17 +96,17 @@

    Callback module for users of the Megaco application

    This module defines the callback behaviour of Megaco users. A megaco_user compliant callback module must export the following functions:

    The semantics of them and their exact signatures are explained below.

    The user_args configuration parameter which may be used to extend the argument list of the callback functions. For example, the handle_connect function takes -by default two arguments:

    handle_connect(Handle, Version)

    but if the user_args parameter is set to a longer list, such as +by default two arguments:

    handle_connect(Handle, Version)

    but if the user_args parameter is set to a longer list, such as [SomePid,SomeTableRef], the callback function is expected to have these (in -this case two) extra arguments last in the argument list:

    handle_connect(Handle, Version, SomePid, SomeTableRef)

    Note

    Must of the functions below has an optional Extra argument (e.g. +this case two) extra arguments last in the argument list:

    handle_connect(Handle, Version, SomePid, SomeTableRef)

    Note

    Must of the functions below has an optional Extra argument (e.g. handle_unexpected_trans/4). The functions which takes this argument will be called if and only if one of the functions receive_message/5 or process_received_message/5 was called -with the Extra argument different than ignore_extra.

    DATA TYPES

    action_request() = #'ActionRequest'{}
    -action_reply() = #'ActionReply'{}
    -error_desc() = #'ErrorDescriptor'{}
    -segment_no() = integer()
    conn_handle() = #megaco_conn_handle{}

    The record initially returned by megaco:connect/4,5. It identifies a "virtual" +with the Extra argument different than ignore_extra.

    DATA TYPES

    action_request() = #'ActionRequest'{}
    +action_reply() = #'ActionReply'{}
    +error_desc() = #'ErrorDescriptor'{}
    +segment_no() = integer()
    conn_handle() = #megaco_conn_handle{}

    The record initially returned by megaco:connect/4,5. It identifies a "virtual" connection and may be reused after a reconnect (disconnect + connect).

    protocol_version() = integer()

    Is the actual protocol version. In most cases the protocol version is retrieved from the processed message, but there are exceptions:

    In these cases, the ProtocolVersion default version is obtained from the static /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> mnesia - 4.25.3.1 - urn:uuid:a84654eb-3ed6-c599-eee7-acab1164ba9f + urn:uuid:03e60917-655a-24ea-c418-b892f54dd71c en - 2026-08-21T03:49:26Z + 2042-09-22T17:08:25Z /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_app_a.xhtml differs (HTML document, ASCII text, with very long lines (894)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_app_a.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_app_a.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -45,11 +45,11 @@ %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --module(mnesia_backup). +-module(mnesia_backup). --include_lib("kernel/include/file.hrl"). +-include_lib("kernel/include/file.hrl"). --export([ +-export([ %% Write access open_write/1, write/2, @@ -60,105 +60,105 @@ open_read/1, read/1, close_read/1 - ]). + ]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Backup callback interface --record(backup, {tmp_file, file, file_desc}). +-record(backup, {tmp_file, file, file_desc}). %% Opens backup media for write %% %% Returns {ok, OpaqueData} or {error, Reason} -open_write(OpaqueData) -> +open_write(OpaqueData) -> File = OpaqueData, - Tmp = lists:concat([File,".BUPTMP"]), - file:delete(Tmp), - case disk_log:open([{name, make_ref()}, - {file, Tmp}, - {repair, false}, - {linkto, self()}]) of - {ok, Fd} -> - {ok, #backup{tmp_file = Tmp, file = File, file_desc = Fd}}; - {error, Reason} -> - {error, Reason} + Tmp = lists:concat([File,".BUPTMP"]), + file:delete(Tmp), + case disk_log:open([{name, make_ref()}, + {file, Tmp}, + {repair, false}, + {linkto, self()}]) of + {ok, Fd} -> + {ok, #backup{tmp_file = Tmp, file = File, file_desc = Fd}}; + {error, Reason} -> + {error, Reason} end. %% Writes BackupItems to the backup media %% %% Returns {ok, OpaqueData} or {error, Reason} -write(OpaqueData, BackupItems) -> +write(OpaqueData, BackupItems) -> B = OpaqueData, - case disk_log:log_terms(B#backup.file_desc, BackupItems) of + case disk_log:log_terms(B#backup.file_desc, BackupItems) of ok -> - {ok, B}; - {error, Reason} -> - abort_write(B), - {error, Reason} + {ok, B}; + {error, Reason} -> + abort_write(B), + {error, Reason} end. %% Closes the backup media after a successful backup %% %% Returns {ok, ReturnValueToUser} or {error, Reason} -commit_write(OpaqueData) -> +commit_write(OpaqueData) -> B = OpaqueData, - case disk_log:sync(B#backup.file_desc) of + case disk_log:sync(B#backup.file_desc) of ok -> - case disk_log:close(B#backup.file_desc) of + case disk_log:close(B#backup.file_desc) of ok -> - file:delete(B#backup.file), - case file:rename(B#backup.tmp_file, B#backup.file) of + file:delete(B#backup.file), + case file:rename(B#backup.tmp_file, B#backup.file) of ok -> - {ok, B#backup.file}; - {error, Reason} -> - {error, Reason} + {ok, B#backup.file}; + {error, Reason} -> + {error, Reason} end; - {error, Reason} -> - {error, Reason} + {error, Reason} -> + {error, Reason} end; - {error, Reason} -> - {error, Reason} + {error, Reason} -> + {error, Reason} end. %% Closes the backup media after an interrupted backup %% %% Returns {ok, ReturnValueToUser} or {error, Reason} -abort_write(BackupRef) -> - Res = disk_log:close(BackupRef#backup.file_desc), - file:delete(BackupRef#backup.tmp_file), +abort_write(BackupRef) -> + Res = disk_log:close(BackupRef#backup.file_desc), + file:delete(BackupRef#backup.tmp_file), case Res of ok -> - {ok, BackupRef#backup.file}; - {error, Reason} -> - {error, Reason} + {ok, BackupRef#backup.file}; + {error, Reason} -> + {error, Reason} end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Restore callback interface --record(restore, {file, file_desc, cont}). +-record(restore, {file, file_desc, cont}). %% Opens backup media for read %% %% Returns {ok, OpaqueData} or {error, Reason} -open_read(OpaqueData) -> +open_read(OpaqueData) -> File = OpaqueData, - case file:read_file_info(File) of - {error, Reason} -> - {error, Reason}; + case file:read_file_info(File) of + {error, Reason} -> + {error, Reason}; _FileInfo -> %% file exists - case disk_log:open([{file, File}, - {name, make_ref()}, - {repair, false}, - {mode, read_only}, - {linkto, self()}]) of - {ok, Fd} -> - {ok, #restore{file = File, file_desc = Fd, cont = start}}; - {repaired, Fd, _, {badbytes, 0}} -> - {ok, #restore{file = File, file_desc = Fd, cont = start}}; - {repaired, Fd, _, _} -> - {ok, #restore{file = File, file_desc = Fd, cont = start}}; - {error, Reason} -> - {error, Reason} + case disk_log:open([{file, File}, + {name, make_ref()}, + {repair, false}, + {mode, read_only}, + {linkto, self()}]) of + {ok, Fd} -> + {ok, #restore{file = File, file_desc = Fd, cont = start}}; + {repaired, Fd, _, {badbytes, 0}} -> + {ok, #restore{file = File, file_desc = Fd, cont = start}}; + {repaired, Fd, _, _} -> + {ok, #restore{file = File, file_desc = Fd, cont = start}}; + {error, Reason} -> + {error, Reason} end end. @@ -167,30 +167,30 @@ %% Returns {ok, OpaqueData, BackupItems} or {error, Reason} %% %% BackupItems == [] is interpreted as eof -read(OpaqueData) -> +read(OpaqueData) -> R = OpaqueData, Fd = R#restore.file_desc, - case disk_log:chunk(Fd, R#restore.cont) of - {error, Reason} -> - {error, {"Possibly truncated", Reason}}; + case disk_log:chunk(Fd, R#restore.cont) of + {error, Reason} -> + {error, {"Possibly truncated", Reason}}; eof -> - {ok, R, []}; - {Cont, []} -> - read(R#restore{cont = Cont}); - {Cont, BackupItems, _BadBytes} -> - {ok, R#restore{cont = Cont}, BackupItems}; - {Cont, BackupItems} -> - {ok, R#restore{cont = Cont}, BackupItems} /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_app_b.xhtml differs (HTML document, ASCII text, with very long lines (1047)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_app_b.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_app_b.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -17,10 +17,10 @@

    Appendix B: Activity Access Callback Interface

    -

    mnesia_access Callback Behavior

    -module(mnesia_frag).
    +

    mnesia_access Callback Behavior

    -module(mnesia_frag).
     
     %% Callback functions when accessed within an activity
    --export([
    +-export([
              lock/4,
              write/5, delete/5, delete_object/5,
              read/5, match_object/5, all_keys/4,
    @@ -29,242 +29,242 @@
              foldl/6, foldr/6, table_info/4,
              first/3, next/4, prev/4, last/3,
              clear_table/4
    -        ]).
    +        ]).
     
     %% Callback functions which provides transparent
     %% access of fragmented tables from any activity
     %% access context.
     
    -lock(ActivityId, Opaque, {table , Tab}, LockKind) ->
    -    case frag_names(Tab) of
    -        [Tab] ->
    -            mnesia:lock(ActivityId, Opaque, {table, Tab}, LockKind);
    +lock(ActivityId, Opaque, {table , Tab}, LockKind) ->
    +    case frag_names(Tab) of
    +        [Tab] ->
    +            mnesia:lock(ActivityId, Opaque, {table, Tab}, LockKind);
             Frags ->
    -            DeepNs = [mnesia:lock(ActivityId, Opaque, {table, F}, LockKind) ||
    -                         F <- Frags],
    -            mnesia_lib:uniq(lists:append(DeepNs))
    +            DeepNs = [mnesia:lock(ActivityId, Opaque, {table, F}, LockKind) ||
    +                         F <- Frags],
    +            mnesia_lib:uniq(lists:append(DeepNs))
         end;
     
    -lock(ActivityId, Opaque, LockItem, LockKind) ->
    -    mnesia:lock(ActivityId, Opaque, LockItem, LockKind).
    +lock(ActivityId, Opaque, LockItem, LockKind) ->
    +    mnesia:lock(ActivityId, Opaque, LockItem, LockKind).
     
    -write(ActivityId, Opaque, Tab, Rec, LockKind) ->
    -    Frag = record_to_frag_name(Tab, Rec),
    -    mnesia:write(ActivityId, Opaque, Frag, Rec, LockKind).
    -
    -delete(ActivityId, Opaque, Tab, Key, LockKind) ->
    -    Frag = key_to_frag_name(Tab, Key),
    -    mnesia:delete(ActivityId, Opaque, Frag, Key, LockKind).
    -
    -delete_object(ActivityId, Opaque, Tab, Rec, LockKind) ->
    -    Frag = record_to_frag_name(Tab, Rec),
    -    mnesia:delete_object(ActivityId, Opaque, Frag, Rec, LockKind).
    -
    -read(ActivityId, Opaque, Tab, Key, LockKind) ->
    -    Frag = key_to_frag_name(Tab, Key),
    -    mnesia:read(ActivityId, Opaque, Frag, Key, LockKind).
    -
    -match_object(ActivityId, Opaque, Tab, HeadPat, LockKind) ->
    -    MatchSpec = [{HeadPat, [], ['$_']}],
    -    select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
    -
    -select(ActivityId, Opaque, Tab, MatchSpec, LockKind) ->
    -    do_select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
    -
    -
    -select(ActivityId, Opaque, Tab, MatchSpec, Limit, LockKind) ->
    -    init_select(ActivityId, Opaque, Tab, MatchSpec, Limit, LockKind).
    -
    -select_cont(_Tid,_,{frag_cont, '$end_of_table', [],_}) -> '$end_of_table';
    -select_cont(Tid,Ts,{frag_cont, '$end_of_table', [{Tab,Node,Type}|Rest],Args}) ->
    -    {Spec,LockKind,Limit} = Args,
    -    InitFun = fun(FixedSpec) -> mnesia:dirty_sel_init(Node,Tab,FixedSpec,Limit,Type) end,
    -    Res = mnesia:fun_select(Tid,Ts,Tab,Spec,LockKind,Tab,InitFun,Limit,Node,Type),
    -    frag_sel_cont(Res, Rest, Args);
    -select_cont(Tid,Ts,{frag_cont, Cont, TabL, Args}) ->
    -    frag_sel_cont(mnesia:select_cont(Tid,Ts,Cont),TabL,Args);
    -select_cont(Tid,Ts,Else) ->
    -    mnesia:select_cont(Tid,Ts,Else).
    -
    -all_keys(ActivityId, Opaque, Tab, LockKind) ->
    -    Match = [mnesia:all_keys(ActivityId, Opaque, Frag, LockKind)
    -             || Frag <- frag_names(Tab)],
    -    lists:append(Match).
    +write(ActivityId, Opaque, Tab, Rec, LockKind) ->
    +    Frag = record_to_frag_name(Tab, Rec),
    +    mnesia:write(ActivityId, Opaque, Frag, Rec, LockKind).
    +
    +delete(ActivityId, Opaque, Tab, Key, LockKind) ->
    +    Frag = key_to_frag_name(Tab, Key),
    +    mnesia:delete(ActivityId, Opaque, Frag, Key, LockKind).
    +
    +delete_object(ActivityId, Opaque, Tab, Rec, LockKind) ->
    +    Frag = record_to_frag_name(Tab, Rec),
    +    mnesia:delete_object(ActivityId, Opaque, Frag, Rec, LockKind).
    +
    +read(ActivityId, Opaque, Tab, Key, LockKind) ->
    +    Frag = key_to_frag_name(Tab, Key),
    +    mnesia:read(ActivityId, Opaque, Frag, Key, LockKind).
    +
    +match_object(ActivityId, Opaque, Tab, HeadPat, LockKind) ->
    +    MatchSpec = [{HeadPat, [], ['$_']}],
    +    select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
    +
    +select(ActivityId, Opaque, Tab, MatchSpec, LockKind) ->
    +    do_select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
    +
    +
    +select(ActivityId, Opaque, Tab, MatchSpec, Limit, LockKind) ->
    +    init_select(ActivityId, Opaque, Tab, MatchSpec, Limit, LockKind).
    +
    +select_cont(_Tid,_,{frag_cont, '$end_of_table', [],_}) -> '$end_of_table';
    +select_cont(Tid,Ts,{frag_cont, '$end_of_table', [{Tab,Node,Type}|Rest],Args}) ->
    +    {Spec,LockKind,Limit} = Args,
    +    InitFun = fun(FixedSpec) -> mnesia:dirty_sel_init(Node,Tab,FixedSpec,Limit,Type) end,
    +    Res = mnesia:fun_select(Tid,Ts,Tab,Spec,LockKind,Tab,InitFun,Limit,Node,Type),
    +    frag_sel_cont(Res, Rest, Args);
    +select_cont(Tid,Ts,{frag_cont, Cont, TabL, Args}) ->
    +    frag_sel_cont(mnesia:select_cont(Tid,Ts,Cont),TabL,Args);
    +select_cont(Tid,Ts,Else) ->
    +    mnesia:select_cont(Tid,Ts,Else).
    +
    +all_keys(ActivityId, Opaque, Tab, LockKind) ->
    +    Match = [mnesia:all_keys(ActivityId, Opaque, Frag, LockKind)
    +             || Frag <- frag_names(Tab)],
    +    lists:append(Match).
     
    -clear_table(ActivityId, Opaque, Tab, Obj) ->
    -    [mnesia:clear_table(ActivityId, Opaque, Frag, Obj)  || Frag <- frag_names(Tab)],
    +clear_table(ActivityId, Opaque, Tab, Obj) ->
    +    [mnesia:clear_table(ActivityId, Opaque, Frag, Obj)  || Frag <- frag_names(Tab)],
         ok.
     
    -index_match_object(ActivityId, Opaque, Tab, Pat, Attr, LockKind) ->
    +index_match_object(ActivityId, Opaque, Tab, Pat, Attr, LockKind) ->
         Match =
    -        [mnesia:index_match_object(ActivityId, Opaque, Frag, Pat, Attr, LockKind)
    -         || Frag <- frag_names(Tab)],
    -    lists:append(Match).
    +        [mnesia:index_match_object(ActivityId, Opaque, Frag, Pat, Attr, LockKind)
    +         || Frag <- frag_names(Tab)],
    +    lists:append(Match).
     
    -index_read(ActivityId, Opaque, Tab, Key, Attr, LockKind) ->
    +index_read(ActivityId, Opaque, Tab, Key, Attr, LockKind) ->
         Match =
    -        [mnesia:index_read(ActivityId, Opaque, Frag, Key, Attr, LockKind)
    -         || Frag <- frag_names(Tab)],
    -    lists:append(Match).
    -
    -foldl(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
    -    Fun2 = fun(Frag, A) ->
    -                   mnesia:foldl(ActivityId, Opaque, Fun, A, Frag, LockKind)
    +        [mnesia:index_read(ActivityId, Opaque, Frag, Key, Attr, LockKind)
    +         || Frag <- frag_names(Tab)],
    +    lists:append(Match).
    +
    +foldl(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
    +    Fun2 = fun(Frag, A) ->
    +                   mnesia:foldl(ActivityId, Opaque, Fun, A, Frag, LockKind)
                end,
    -    lists:foldl(Fun2, Acc, frag_names(Tab)).
    +    lists:foldl(Fun2, Acc, frag_names(Tab)).
     
    -foldr(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
    -    Fun2 = fun(Frag, A) ->
    -                   mnesia:foldr(ActivityId, Opaque, Fun, A, Frag, LockKind)
    +foldr(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
    +    Fun2 = fun(Frag, A) ->
    +                   mnesia:foldr(ActivityId, Opaque, Fun, A, Frag, LockKind)
                end,
    -    lists:foldr(Fun2, Acc, frag_names(Tab)).
    +    lists:foldr(Fun2, Acc, frag_names(Tab)).
     
    -table_info(ActivityId, Opaque, {Tab, Key}, Item) ->
    -    Frag = key_to_frag_name(Tab, Key),
    -    table_info2(ActivityId, Opaque, Tab, Frag, Item);
    -table_info(ActivityId, Opaque, Tab, Item) ->
    -    table_info2(ActivityId, Opaque, Tab, Tab, Item).
    +table_info(ActivityId, Opaque, {Tab, Key}, Item) ->
    +    Frag = key_to_frag_name(Tab, Key),
    +    table_info2(ActivityId, Opaque, Tab, Frag, Item);
    +table_info(ActivityId, Opaque, Tab, Item) ->
    +    table_info2(ActivityId, Opaque, Tab, Tab, Item).
     
    -table_info2(ActivityId, Opaque, Tab, Frag, Item) ->
    +table_info2(ActivityId, Opaque, Tab, Frag, Item) ->
         case Item of
             size ->
    -            SumFun = fun({_, Size}, Acc) -> Acc + Size end,
    -            lists:foldl(SumFun, 0, frag_size(ActivityId, Opaque, Tab));
    +            SumFun = fun({_, Size}, Acc) -> Acc + Size end,
    +            lists:foldl(SumFun, 0, frag_size(ActivityId, Opaque, Tab));
             memory ->
    /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_app_c.xhtml differs (HTML document, ASCII text, with very long lines (1038))
    --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_app_c.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_app_c.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -17,140 +17,140 @@
       
     
         

    Appendix C: Fragmented Table Hashing Callback Interface

    -

    mnesia_frag_hash Callback Behavior

    -module(mnesia_frag_hash).
    --compile([{nowarn_deprecated_function, [{erlang,phash,2}]}]).
    +

    mnesia_frag_hash Callback Behavior

    -module(mnesia_frag_hash).
    +-compile([{nowarn_deprecated_function, [{erlang,phash,2}]}]).
     
     %% Fragmented Table Hashing callback functions
    --export([
    +-export([
              init_state/2,
              add_frag/1,
              del_frag/1,
              key_to_frag_number/2,
              match_spec_to_frag_numbers/2
    -        ]).
    -record(hash_state,
    -    {n_fragments,
    +        ]).
    -record(hash_state,
    +    {n_fragments,
          next_n_to_split,
          n_doubles,
    -     function}).
    +     function}).
     
     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    --spec init_state(Tab, State) -> NewState when
    -      Tab :: atom(),
    -      State :: term(),
    -      NewState :: term().
    -init_state(_Tab, State) when State == undefined ->
    -    #hash_state{n_fragments     = 1,
    +-spec init_state(Tab, State) -> NewState when
    +      Tab :: atom(),
    +      State :: term(),
    +      NewState :: term().
    +init_state(_Tab, State) when State == undefined ->
    +    #hash_state{n_fragments     = 1,
                     next_n_to_split = 1,
                     n_doubles       = 0,
    -                function        = phash2}.
    +                function        = phash2}.
     
    -convert_old_state({hash_state, N, P, L}) ->
    -    #hash_state{n_fragments     = N,
    +convert_old_state({hash_state, N, P, L}) ->
    +    #hash_state{n_fragments     = N,
                     next_n_to_split = P,
                     n_doubles       = L,
    -                function        = phash}.
    +                function        = phash}.
     
     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    --spec add_frag(State :: term()) -> {NewState, IterFrags, AdditionalLockFrags} when
    -      NewState :: term(),
    -      IterFrags :: [integer()],
    -      AdditionalLockFrags :: [integer()].
    -add_frag(#hash_state{next_n_to_split = SplitN, n_doubles = L, n_fragments = N} = State) ->
    +-spec add_frag(State :: term()) -> {NewState, IterFrags, AdditionalLockFrags} when
    +      NewState :: term(),
    +      IterFrags :: [integer()],
    +      AdditionalLockFrags :: [integer()].
    +add_frag(#hash_state{next_n_to_split = SplitN, n_doubles = L, n_fragments = N} = State) ->
         P = SplitN + 1,
         NewN = N + 1,
    -    State2 = case power2(L) + 1 of
    +    State2 = case power2(L) + 1 of
             P2 when P2 == P ->
    -            State#hash_state{n_fragments      = NewN,
    +            State#hash_state{n_fragments      = NewN,
                                  n_doubles        = L + 1,
    -                             next_n_to_split  = 1};
    +                             next_n_to_split  = 1};
             _ ->
    -            State#hash_state{n_fragments     = NewN,
    -                             next_n_to_split = P}
    +            State#hash_state{n_fragments     = NewN,
    +                             next_n_to_split = P}
         end,
    -    {State2, [SplitN], [NewN]};
    -add_frag(OldState) ->
    -    State = convert_old_state(OldState),
    -    add_frag(State).
    +    {State2, [SplitN], [NewN]};
    +add_frag(OldState) ->
    +    State = convert_old_state(OldState),
    +    add_frag(State).
     
     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     
    --spec del_frag(State :: term()) -> {NewState, IterFrags, AdditionalLockFrags} when
    -      NewState :: term(),
    -      IterFrags :: [integer()],
    -      AdditionalLockFrags :: [integer()].
    -del_frag(#hash_state{next_n_to_split = SplitN, n_doubles = L, n_fragments = N} = State) ->
    +-spec del_frag(State :: term()) -> {NewState, IterFrags, AdditionalLockFrags} when
    +      NewState :: term(),
    +      IterFrags :: [integer()],
    +      AdditionalLockFrags :: [integer()].
    +del_frag(#hash_state{next_n_to_split = SplitN, n_doubles = L, n_fragments = N} = State) ->
         P = SplitN - 1,
         if
             P < 1 ->
                 L2 = L - 1,
    -            MergeN = power2(L2),
    -            State2 = State#hash_state{n_fragments     = N - 1,
    +            MergeN = power2(L2),
    +            State2 = State#hash_state{n_fragments     = N - 1,
                                           next_n_to_split = MergeN,
    -                                      n_doubles       = L2},
    -            {State2, [N], [MergeN]};
    +                                      n_doubles       = L2},
    +            {State2, [N], [MergeN]};
             true ->
                 MergeN = P,
    -            State2 = State#hash_state{n_fragments     = N - 1,
    -                                      next_n_to_split = MergeN},
    -            {State2, [N], [MergeN]}
    +            State2 = State#hash_state{n_fragments     = N - 1,
    +                                      next_n_to_split = MergeN},
    +            {State2, [N], [MergeN]}
         end;
    -del_frag(OldState) ->
    -    State = convert_old_state(OldState),
    -    del_frag(State).
    +del_frag(OldState) ->
    +    State = convert_old_state(OldState),
    +    del_frag(State).
     
     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    --spec key_to_frag_number(State, Key) -> Fragnum when
    -      State :: term(),
    -      Key :: term(),
    -      Fragnum :: integer().
    -key_to_frag_number(#hash_state{function = phash, n_fragments = N, n_doubles = L}, Key) ->
    -    A = erlang:phash(Key, power2(L + 1)),
    +-spec key_to_frag_number(State, Key) -> Fragnum when
    +      State :: term(),
    +      Key :: term(),
    +      Fragnum :: integer().
    +key_to_frag_number(#hash_state{function = phash, n_fragments = N, n_doubles = L}, Key) ->
    +    A = erlang:phash(Key, power2(L + 1)),
         if
             A > N ->
    -            A - power2(L);
    +            A - power2(L);
             true ->
                 A
         end;
    -key_to_frag_number(#hash_state{function = phash2, n_fragments = N, n_doubles = L}, Key) ->
    -    A = erlang:phash2(Key, power2(L + 1)) + 1,
    +key_to_frag_number(#hash_state{function = phash2, n_fragments = N, n_doubles = L}, Key) ->
    +    A = erlang:phash2(Key, power2(L + 1)) + 1,
         if
             A > N ->
    -            A - power2(L);
    +            A - power2(L);
             true ->
                 A
         end;
    -key_to_frag_number(OldState, Key) ->
    -    State = convert_old_state(OldState),
    -    key_to_frag_number(State, Key).
    +key_to_frag_number(OldState, Key) ->
    +    State = convert_old_state(OldState),
    +    key_to_frag_number(State, Key).
     
     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    --spec match_spec_to_frag_numbers(State, MatchSpec) -> Fragnums when
    -      State :: term(),
    -      MatchSpec :: ets:match_spec(),
    -      Fragnums :: [integer()].
    -match_spec_to_frag_numbers(#hash_state{n_fragments = N} = State, MatchSpec) ->
    +-spec match_spec_to_frag_numbers(State, MatchSpec) -> Fragnums when
    +      State :: term(),
    +      MatchSpec :: ets:match_spec(),
    +      Fragnums :: [integer()].
    +match_spec_to_frag_numbers(#hash_state{n_fragments = N} = State, MatchSpec) ->
         case MatchSpec of
    -        [{HeadPat, _, _}] when is_tuple(HeadPat), tuple_size(HeadPat) > 2 ->
    -            KeyPat = element(2, HeadPat),
    -            case has_var(KeyPat) of
    +        [{HeadPat, _, _}] when is_tuple(HeadPat), tuple_size(HeadPat) > 2 ->
    +            KeyPat = element(2, HeadPat),
    +            case has_var(KeyPat) of
                     false ->
    -                    [key_to_frag_number(State, KeyPat)];
    +                    [key_to_frag_number(State, KeyPat)];
                     true ->
    -                    lists:seq(1, N)
    +                    lists:seq(1, N)
                 end;
             _ ->
    -            lists:seq(1, N)
    +            lists:seq(1, N)
         end;
    /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap2.xhtml differs (HTML document, ASCII text, with very long lines (1074))
    --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap2.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap2.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -23,16 +23,16 @@
     mandatory procedures through examples:

    • Starting the Erlang session.
    • Specifying the Mnesia directory where the database is to be stored.
    • Initializing a new database schema with an attribute that specifies on which node, or nodes, that database is to operate.
    • Starting Mnesia.
    • Creating and populating the database tables.

    Starting Mnesia for the First Time

    This section provides a simplified demonstration of a Mnesia system startup. The dialogue from the Erlang shell is as follows:

    % erl -mnesia dir '"/tmp/funky"'
    -Erlang/OTP 27 [erts-15.1.2]
    +Erlang/OTP 27 [erts-15.1.2]
     
    -Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
    -1> mnesia:create_schema([node()]).
    +Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
    +1> mnesia:create_schema([node()]).
     ok
    -2> mnesia:start().
    +2> mnesia:start().
     ok
    -3> mnesia:create_table(funky, []).
    -{atomic,ok}
    -4> mnesia:info().
    +3> mnesia:create_table(funky, []).
    +{atomic,ok}
    +4> mnesia:info().
     ---> Processes holding locks <--- 
     ---> Processes waiting for locks <--- 
     ---> Participant transactions <--- 
    @@ -44,18 +44,18 @@
     ===> System info in version "4.23.2", debug level = none <===
     opt_disc. Directory "/tmp/funky" is used.
     use fallback at restart = false
    -running db nodes   = [nonode@nohost]
    -stopped db nodes   = []
    -master node tables = []
    -remote             = []
    -ram_copies         = [funky]
    -disc_copies        = [schema]
    -disc_only_copies   = []
    -[{nonode@nohost,disc_copies}] = [schema]
    -[{nonode@nohost,ram_copies}] = [funky]
    +running db nodes   = [nonode@nohost]
    +stopped db nodes   = []
    +master node tables = []
    +remote             = []
    +ram_copies         = [funky]
    +disc_copies        = [schema]
    +disc_only_copies   = []
    +[{nonode@nohost,disc_copies}] = [schema]
    +[{nonode@nohost,ram_copies}] = [funky]
     3 transactions committed, 0 aborted, 0 restarted, 2 logged to disc
     0 held locks, 0 in queue; 0 local transactions, 0 remote
    -0 transactions waits for other nodes: []
    +0 transactions waits for other nodes: []
     ok

    In this example, the following actions are performed:

    • Step 1: The Erlang system is started from the UNIX prompt with a flag -mnesia dir '"/tmp/funky"', which indicates in which directory to store the data.
    • Step 2: A new empty schema is initialized on the local node by evaluating @@ -97,28 +97,28 @@ Employee }|--|| Dept: At_dep Employee }|--|{ Project: in_proj

    The database model is as follows:

    • There are three entities: department, employee, and project.
    • There are three relationships between these entities:
      1. A department is managed by an employee, hence the manager relationship.
      2. An employee works at a department, hence the at_dep relationship.
      3. Each employee works on a number of projects, hence the in_proj relationship.

    Defining Structure and Content

    First the record definitions are entered into a text file named company.hrl. -This file defines the following structure for the example database:

    -record(employee, {emp_no,
    +This file defines the following structure for the example database:

    -record(employee, {emp_no,
                        name,
                        salary,
                        sex,
                        phone,
    -                   room_no}).
    +                   room_no}).
     
    --record(dept, {id,
    -               name}).
    +-record(dept, {id,
    +               name}).
     
    --record(project, {name,
    -                  number}).
    +-record(project, {name,
    +                  number}).
     
     
    --record(manager, {emp,
    -                  dept}).
    +-record(manager, {emp,
    +                  dept}).
     
    --record(at_dep, {emp,
    -                 dept_id}).
    +-record(at_dep, {emp,
    +                 dept_id}).
     
    --record(in_proj, {emp,
    -                  proj_name}).

    The structure defines six tables in the database. In Mnesia, the function +-record(in_proj, {emp, + proj_name}).

    The structure defines six tables in the database. In Mnesia, the function mnesia:create_table(Name, Opts) creates tables. Name is the table name.

    Note

    The current version of Mnesia does not require that the name of the table is the same as the record name, see @@ -129,28 +129,28 @@ preprocessor and evaluates to a list containing the names of the different fields for a record.

    Program

    The following shell interaction starts Mnesia and initializes the schema for the Company database:

    % erl -mnesia dir '"/ldisc/scratch/Mnesia.Company"'
    -Erlang/OTP 27 [erts-15.1.2]
    +Erlang/OTP 27 [erts-15.1.2]
     
    -Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
    -1> mnesia:create_schema([node()]).
    +Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
    +1> mnesia:create_schema([node()]).
     ok
    -2> mnesia:start().
    -ok

    The following program module creates and populates previously defined tables:

    -include_lib("stdlib/include/qlc.hrl").
    --include("company.hrl").
    -
    -init() ->
    -    mnesia:create_table(employee,
    -                        [{attributes, record_info(fields, employee)}]),
    -    mnesia:create_table(dept,
    -                        [{attributes, record_info(fields, dept)}]),
    -    mnesia:create_table(project,
    -                        [{attributes, record_info(fields, project)}]),
    -    mnesia:create_table(manager, [{type, bag},
    -                                  {attributes, record_info(fields, manager)}]),
    -    mnesia:create_table(at_dep,
    -                         [{attributes, record_info(fields, at_dep)}]),
    -    mnesia:create_table(in_proj, [{type, bag},
    -                                  {attributes, record_info(fields, in_proj)}]).

    Program Explained

    The following commands and functions are used to initiate the Company +2> mnesia:start(). +ok

    The following program module creates and populates previously defined tables:

    -include_lib("stdlib/include/qlc.hrl").
    +-include("company.hrl").
    +
    +init() ->
    +    mnesia:create_table(employee,
    +                        [{attributes, record_info(fields, employee)}]),
    +    mnesia:create_table(dept,
    +                        [{attributes, record_info(fields, dept)}]),
    +    mnesia:create_table(project,
    +                        [{attributes, record_info(fields, project)}]),
    +    mnesia:create_table(manager, [{type, bag},
    +                                  {attributes, record_info(fields, manager)}]),
    +    mnesia:create_table(at_dep,
    +                         [{attributes, record_info(fields, at_dep)}]),
    +    mnesia:create_table(in_proj, [{type, bag},
    +                                  {attributes, record_info(fields, in_proj)}]).

    Program Explained

    The following commands and functions are used to initiate the Company database:

    • % erl -mnesia dir '"/ldisc/scratch/Mnesia.Company"'. This is a UNIX command-line entry that starts the Erlang system. The flag -mnesia dir Dir specifies the location of the database directory. The system responds and @@ -158,9 +158,9 @@ the format mnesia:create_schema(DiscNodeList) and initiates a new schema. In this example, a non-distributed system using only one node is created. Schemas are fully explained in Define a Schema.
    • mnesia:start(). This function starts Mnesia and is fully -explained in Start Mnesia.

    Continuing the dialogue with the Erlang shell produces the following:

    3> company:init().
    -{atomic,ok}
    -4> mnesia:info().
    +explained in Start Mnesia.

    Continuing the dialogue with the Erlang shell produces the following:

    3> company:init().
    +{atomic,ok}
    +4> mnesia:info().
     ---> Processes holding locks <--- 
     ---> Processes waiting for locks <--- 
     ---> Participant transactions <--- 
    @@ -177,18 +177,18 @@
     ===> System info in version "4.23.2", debug level = none <===
     opt_disc. Directory "/ldisc/scratch/Mnesia.Company" is used.
     use fallback at restart = false
    -running db nodes   = [nonode@nohost]
    -stopped db nodes   = []
    -master node tables = []
    -remote             = []
    -ram_copies         = [at_dep,dept,employee,in_proj,manager,project]
    -disc_copies        = [schema]
    -disc_only_copies   = []
    -[{nonode@nohost,disc_copies}] = [schema]
    -[{nonode@nohost,ram_copies}] = [employee,dept,project,manager,at_dep,in_proj]
    +running db nodes   = [nonode@nohost]
    +stopped db nodes   = []
    +master node tables = []
    +remote             = []
    +ram_copies         = [at_dep,dept,employee,in_proj,manager,project]
    +disc_copies        = [schema]
    +disc_only_copies   = []
    +[{nonode@nohost,disc_copies}] = [schema]
    +[{nonode@nohost,ram_copies}] = [employee,dept,project,manager,at_dep,in_proj]
     8 transactions committed, 0 aborted, 0 restarted, 12 logged to disc
     0 held locks, 0 in queue; 0 local transactions, 0 remote
    -0 transactions waits for other nodes: []
    +0 transactions waits for other nodes: []
     ok

    A set of tables is created. The function mnesia:create_table(Name, Opts) creates the required database tables. The options available with Opts are explained in @@ -202,32 +202,32 @@ transactions have been committed, as six successful transactions were run when creating the tables.

    To write a function that inserts an employee record into the database, there must be an at_dep record and a set of in_proj records inserted. Examine the -following code used to complete this action:

    insert_emp(Emp, DeptId, ProjNames) ->
    +following code used to complete this action:

    insert_emp(Emp, DeptId, ProjNames) ->
         Ename = Emp#employee.name,
    -    Fun = fun() ->
    -                  mnesia:write(Emp),
    -                  AtDep = #at_dep{emp = Ename, dept_id = DeptId},
    -                  mnesia:write(AtDep),
    -                  mk_projs(Ename, ProjNames)
    +    Fun = fun() ->
    /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap3.xhtml differs (HTML document, ASCII text, with very long lines (1223))
    --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap3.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap3.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -55,18 +55,18 @@
     changes the format on all records in table Tab. It applies argument Fun to
     all records in the table. Fun must be a function that takes a record of the
     old type, and returns the record of the new type. The table key must not be
    -changed.

    Example:

    -record(old, {key, val}).
    --record(new, {key, val, extra}).
    +changed.

    Example:

    -record(old, {key, val}).
    +-record(new, {key, val, extra}).
     
     Transformer =
    -   fun(X) when record(X, old) ->
    -      #new{key = X#old.key,
    +   fun(X) when record(X, old) ->
    +      #new{key = X#old.key,
                val = X#old.val,
    -           extra = 42}
    +           extra = 42}
        end,
    -{atomic, ok} = mnesia:transform_table(foo, Transformer,
    -                                      record_info(fields, new),
    -                                      new),

    Argument Fun can also be the atom ignore, which indicates that only the +{atomic, ok} = mnesia:transform_table(foo, Transformer, + record_info(fields, new), + new),

    Argument Fun can also be the atom ignore, which indicates that only the metadata about the table is updated. Use of ignore is not recommended (as it creates inconsistencies between the metadata and the actual data) but it is included as a possibility for the user do to an own (offline) transform.

  • mnesia:change_table_copy_type(Tab, Node, ToType) @@ -100,29 +100,29 @@ when starting the Erlang shell or in the application script. Previously, the following example was used to create the directory for the Company database:

    % erl -mnesia dir '"/ldisc/scratch/Mnesia.Company"'
  • If no command-line flag is entered, the Mnesia directory becomes the current working directory on the node where the Erlang shell is started.

  • To start the Company database and get it running on the two specified nodes, -enter the following commands:

    1. On the node a@gin:
     gin % erl -sname a  -mnesia dir '"/ldisc/scratch/Mnesia.company"'
    1. On the node b@skeppet:
    skeppet % erl -sname b -mnesia dir '"/ldisc/scratch/Mnesia.company"'
    1. On one of the two nodes:
    (a@gin)1> mnesia:create_schema([a@gin, b@skeppet]).
    1. The function mnesia:start() is called on both nodes.
    2. To initialize the database, execute the following code on one of the two -nodes:
    dist_init() ->
    -    mnesia:create_table(employee,
    -                         [{ram_copies, [a@gin, b@skeppet]},
    -                          {attributes, record_info(fields,
    -                                                   employee)}]),
    -    mnesia:create_table(dept,
    -                         [{ram_copies, [a@gin, b@skeppet]},
    -                          {attributes, record_info(fields, dept)}]),
    -    mnesia:create_table(project,
    -                         [{ram_copies, [a@gin, b@skeppet]},
    -                          {attributes, record_info(fields, project)}]),
    -    mnesia:create_table(manager, [{type, bag},
    -                                  {ram_copies, [a@gin, b@skeppet]},
    -                                  {attributes, record_info(fields,
    -                                                           manager)}]),
    -    mnesia:create_table(at_dep,
    -                         [{ram_copies, [a@gin, b@skeppet]},
    -                          {attributes, record_info(fields, at_dep)}]),
    -    mnesia:create_table(in_proj,
    -                        [{type, bag},
    -                         {ram_copies, [a@gin, b@skeppet]},
    -                         {attributes, record_info(fields, in_proj)}]).

    As illustrated, the two directories reside on different nodes, because +enter the following commands:

    1. On the node a@gin:
     gin % erl -sname a  -mnesia dir '"/ldisc/scratch/Mnesia.company"'
    1. On the node b@skeppet:
    skeppet % erl -sname b -mnesia dir '"/ldisc/scratch/Mnesia.company"'
    1. On one of the two nodes:
    (a@gin)1> mnesia:create_schema([a@gin, b@skeppet]).
    1. The function mnesia:start() is called on both nodes.
    2. To initialize the database, execute the following code on one of the two +nodes:
    dist_init() ->
    +    mnesia:create_table(employee,
    +                         [{ram_copies, [a@gin, b@skeppet]},
    +                          {attributes, record_info(fields,
    +                                                   employee)}]),
    +    mnesia:create_table(dept,
    +                         [{ram_copies, [a@gin, b@skeppet]},
    +                          {attributes, record_info(fields, dept)}]),
    +    mnesia:create_table(project,
    +                         [{ram_copies, [a@gin, b@skeppet]},
    +                          {attributes, record_info(fields, project)}]),
    +    mnesia:create_table(manager, [{type, bag},
    +                                  {ram_copies, [a@gin, b@skeppet]},
    +                                  {attributes, record_info(fields,
    +                                                           manager)}]),
    +    mnesia:create_table(at_dep,
    +                         [{ram_copies, [a@gin, b@skeppet]},
    +                          {attributes, record_info(fields, at_dep)}]),
    +    mnesia:create_table(in_proj,
    +                        [{type, bag},
    +                         {ram_copies, [a@gin, b@skeppet]},
    +                         {attributes, record_info(fields, in_proj)}]).

    As illustrated, the two directories reside on different nodes, because /ldisc/scratch (the "local" disc) exists on the two different nodes.

    By executing these commands, two Erlang nodes are configured to run the Company database, and therefore, initialize the database. This is required only once when setting up. The next time the system is started, @@ -133,7 +133,7 @@ Code that manipulate Mnesia data behaves identically regardless of where the data resides.

    The function mnesia:stop() stops Mnesia on the node where the function is executed. The functions mnesia:start/0 and mnesia:stop/0 -work on the "local" Mnesia system. No functions start or stop a set of nodes.

    Startup Procedure

    Start Mnesia by calling the following function:

    mnesia:start().

    This function initiates the DBMS locally.

    The choice of configuration alters the location and load order of the tables. +work on the "local" Mnesia system. No functions start or stop a set of nodes.

    Startup Procedure

    Start Mnesia by calling the following function:

    mnesia:start().

    This function initiates the DBMS locally.

    The choice of configuration alters the location and load order of the tables. The alternatives are as follows:

    1. Tables that are only stored locally are initialized from the local Mnesia directory.
    2. Replicated tables that reside locally as well as somewhere else are either initiated from disc or by copying the entire table from the other node, @@ -156,9 +156,9 @@ from disc at a faster rate. The function forces tables to be loaded from disc regardless of the network situation.

      Thus, it can be assumed that if an application wants to use tables a and b, the application must perform some action similar to following before it can use -the tables:

      case mnesia:wait_for_tables([a, b], 20000) of
      -  {timeout, RemainingTabs} ->
      -    panic(RemainingTabs);
      +the tables:

      case mnesia:wait_for_tables([a, b], 20000) of
      +  {timeout, RemainingTabs} ->
      +    panic(RemainingTabs);
         ok ->
           synced
       end.

      Warning

      When tables are forcefully loaded from the local disc, all operations that @@ -178,13 +178,13 @@ key, whereas a table of type bag can have an arbitrary number of records per key. The key for each record is always the first attribute of the record.

      The following example illustrates the difference between type set and -bag:

       f() ->
      -    F = fun() ->
      -          mnesia:write({foo, 1, 2}),
      -          mnesia:write({foo, 1, 3}),
      -          mnesia:read({foo, 1})
      +bag:

       f() ->
      +    F = fun() ->
      +          mnesia:write({foo, 1, 2}),
      +          mnesia:write({foo, 1, 3}),
      +          mnesia:read({foo, 1})
               end,
      -    mnesia:transaction(F).

      This transaction returns the list [{foo,1,3}] if table foo is of type + mnesia:transaction(F).

      This transaction returns the list [{foo,1,3}] if table foo is of type set. However, the list [{foo,1,2}, {foo,1,3}] is returned if the table is of type bag.

      Mnesia tables can never contain duplicates of the same record in the same table. Duplicate records have attributes with the same contents and key.

    3. {disc_copies, NodeList}, where NodeList is a list of the nodes where @@ -228,11 +228,11 @@ table. All records stored in the table must have this name as their first element. record_name defaults to the name of the table. For more information, see -Record Names versus Table Names.

    4. As an example, consider the following record definition:

      -record(funky, {x, y}).

      The following call would create a table that is replicated on two nodes, has an -extra index on attribute y, and is of type bag.

      mnesia:create_table(funky, [{disc_copies, [N1, N2]}, {index, [y]},
      -                            {type, bag}, {attributes, record_info(fields, funky)}]).

      Whereas a call to the following default code values would return a table with a +Record Names versus Table Names.

      As an example, consider the following record definition:

      -record(funky, {x, y}).

      The following call would create a table that is replicated on two nodes, has an +extra index on attribute y, and is of type bag.

      mnesia:create_table(funky, [{disc_copies, [N1, N2]}, {index, [y]},
      +                            {type, bag}, {attributes, record_info(fields, funky)}]).

      Whereas a call to the following default code values would return a table with a RAM copy on the local node, no extra indexes, and the attributes defaulted to -the list [key,val].

      mnesia:create_table(stuff, [])
      +the list [key,val].

      mnesia:create_table(stuff, [])
      /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap4.xhtml differs (HTML document, ASCII text, with very long lines (1903)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap4.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap4.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -31,14 +31,14 @@ and delete Mnesia records. The Fun is evaluated as a transaction that either commits or terminates. If a transaction succeeds in executing the Fun, it replicates the action on all nodes involved, or terminates if an error occurs.

      The following example shows a transaction that raises the salary of certain -employee numbers:

      raise(Eno, Raise) ->
      -    F = fun() ->
      -                [E] = mnesia:read(employee, Eno, write),
      +employee numbers:

      raise(Eno, Raise) ->
      +    F = fun() ->
      +                [E] = mnesia:read(employee, Eno, write),
                       Salary = E#employee.salary + Raise,
      -                New = E#employee{salary = Salary},
      -                mnesia:write(New)
      +                New = E#employee{salary = Salary},
      +                mnesia:write(New)
               end,
      -    mnesia:transaction(F).

      The function raise/2 contains a Fun made up of four code lines. This Fun is + mnesia:transaction(F).

      The function raise/2 contains a Fun made up of four code lines. This Fun is called by the statement mnesia:transaction(F) and returns a value.

      The Mnesia transaction system facilitates the construction of reliable, distributed systems by providing the following important properties:

      • The transaction handler ensures that a Fun, which is placed inside a transaction, does not interfere with operations embedded in other transactions @@ -102,15 +102,15 @@ The Fun in the transaction is evaluated once more.

        It is therefore important that the code inside the Fun given to mnesia:transaction/1 is pure. Some strange results can occur if, for example, messages are sent by the transaction Fun. The following example illustrates this -situation:

        bad_raise(Eno, Raise) ->
        -    F = fun() ->
        -                [E] = mnesia:read({employee, Eno}),
        +situation:

        bad_raise(Eno, Raise) ->
        +    F = fun() ->
        +                [E] = mnesia:read({employee, Eno}),
                         Salary = E#employee.salary + Raise,
        -                New = E#employee{salary = Salary},
        -                io:format("Trying to write ... ~n", []),
        -                mnesia:write(New)
        +                New = E#employee{salary = Salary},
        +                io:format("Trying to write ... ~n", []),
        +                mnesia:write(New)
                 end,
        -    mnesia:transaction(F).

        This transaction can write the text "Trying to write ... " 1000 times to the + mnesia:transaction(F).

        This transaction can write the text "Trying to write ... " 1000 times to the terminal. However, Mnesia guarantees that each transaction will eventually run. As a result, Mnesia is not only deadlock free, but also livelock free.

        The Mnesia programmer cannot prioritize one particular transaction to execute before other transactions that are waiting to execute. As a result, the Mnesia @@ -151,13 +151,13 @@ fails. Such applications can benefit from using sticky locks instead of the normal locking scheme.

        A sticky lock is a lock that stays in place at a node, after the transaction that first acquired the lock has terminated. To illustrate this, assume that the -following transaction is executed:

        F = fun() ->
        -      mnesia:write(#foo{a = kalle})
        +following transaction is executed:

        F = fun() ->
        +      mnesia:write(#foo{a = kalle})
             end,
        -mnesia:transaction(F).

        The foo table is replicated on the two nodes N1 and N2.

        Normal locking requires the following:

        • One network RPC (two messages) to acquire the write lock
        • Three network messages to execute the two-phase commit protocol

        If sticky locks are used, the code must first be changed as follows:

        F = fun() ->
        -      mnesia:s_write(#foo{a = kalle})
        +mnesia:transaction(F).

        The foo table is replicated on the two nodes N1 and N2.

        Normal locking requires the following:

        • One network RPC (two messages) to acquire the write lock
        • Three network messages to execute the two-phase commit protocol

        If sticky locks are used, the code must first be changed as follows:

        F = fun() ->
        +      mnesia:s_write(#foo{a = kalle})
             end,
        -mnesia:transaction(F).

        This code uses the function s_write/1 instead of the +mnesia:transaction(F).

        This code uses the function s_write/1 instead of the function write/1 The function s_write/1 sets a sticky lock instead of a normal lock. If the table is not replicated, sticky locks have no special effect. If the table is replicated, and a sticky lock is set on node @@ -177,8 +177,8 @@ following two functions are used to set explicit table locks for read and write operations:

        Alternative syntax for acquisition of table locks is as follows:

        mnesia:lock({table, Tab}, read)
        -mnesia:lock({table, Tab}, write)

        The matching operations in Mnesia can either lock the entire table or only a +on table Tab.

      Alternative syntax for acquisition of table locks is as follows:

      mnesia:lock({table, Tab}, read)
      +mnesia:lock({table, Tab}, write)

      The matching operations in Mnesia can either lock the entire table or only a single record (when the key is bound in the pattern).

      Global Locks

      Write locks are normally acquired on all nodes where a replica of the table resides (and is active). Read locks are acquired on one node (the local one if a local replica exists).

      The function mnesia:lock/2 is intended to support table locks (as mentioned @@ -251,78 +251,78 @@ necessarily have to be the same as the table name, although this is the case in most of the examples in this User's Guide. If a table is created without property record_name, the following code ensures that all records in the -tables have the same name as the table:

      mnesia:create_table(subscriber, [])

      However, if the table is created with an explicit record name as argument, as +tables have the same name as the table:

      mnesia:create_table(subscriber, [])

      However, if the table is created with an explicit record name as argument, as shown in the following example, subscriber records can be stored in both of the -tables regardless of the table names:

      TabDef = [{record_name, subscriber}],
      -mnesia:create_table(my_subscriber, TabDef),
      -mnesia:create_table(your_subscriber, TabDef).

      To access such tables, simplified access functions (as described earlier) cannot +tables regardless of the table names:

      TabDef = [{record_name, subscriber}],
      +mnesia:create_table(my_subscriber, TabDef),
      +mnesia:create_table(your_subscriber, TabDef).

      To access such tables, simplified access functions (as described earlier) cannot be used. For example, writing a subscriber record into a table requires the function mnesia:write/3 instead of the simplified functions mnesia:write/1 -and mnesia:s_write/1:

      mnesia:write(subscriber, #subscriber{}, write)
      -mnesia:write(my_subscriber, #subscriber{}, sticky_write)
      -mnesia:write(your_subscriber, #subscriber{}, write)

      The following simple code illustrates the relationship between the simplified +and mnesia:s_write/1:

      mnesia:write(subscriber, #subscriber{}, write)
      +mnesia:write(my_subscriber, #subscriber{}, sticky_write)
      +mnesia:write(your_subscriber, #subscriber{}, write)

      The following simple code illustrates the relationship between the simplified access functions used in most of the examples and their more flexible -counterparts:

      mnesia:dirty_write(Record) ->
      -  Tab = element(1, Record),
      -  mnesia:dirty_write(Tab, Record).
      +counterparts:

      mnesia:dirty_write(Record) ->
      +  Tab = element(1, Record),
      +  mnesia:dirty_write(Tab, Record).
       
      -mnesia:dirty_delete({Tab, Key}) ->
      -  mnesia:dirty_delete(Tab, Key).
      +mnesia:dirty_delete({Tab, Key}) ->
      +  mnesia:dirty_delete(Tab, Key).
       
      -mnesia:dirty_delete_object(Record) ->
      -  Tab = element(1, Record),
      -  mnesia:dirty_delete_object(Tab, Record)
      +mnesia:dirty_delete_object(Record) ->
      +  Tab = element(1, Record),
      +  mnesia:dirty_delete_object(Tab, Record)
       
      -mnesia:dirty_update_counter({Tab, Key}, Incr) ->
      -  mnesia:dirty_update_counter(Tab, Key, Incr).
      +mnesia:dirty_update_counter({Tab, Key}, Incr) ->
      +  mnesia:dirty_update_counter(Tab, Key, Incr).
       
      -mnesia:dirty_read({Tab, Key}) ->
      -  Tab = element(1, Record),
      -  mnesia:dirty_read(Tab, Key).
      +mnesia:dirty_read({Tab, Key}) ->
      +  Tab = element(1, Record),
      +  mnesia:dirty_read(Tab, Key).
       
      -mnesia:dirty_match_object(Pattern) ->
      -  Tab = element(1, Pattern),
      -  mnesia:dirty_match_object(Tab, Pattern).
      +mnesia:dirty_match_object(Pattern) ->
      +  Tab = element(1, Pattern),
      +  mnesia:dirty_match_object(Tab, Pattern).
       
      -mnesia:dirty_index_match_object(Pattern, Attr)
      -  Tab = element(1, Pattern),
      -  mnesia:dirty_index_match_object(Tab, Pattern, Attr).
      +mnesia:dirty_index_match_object(Pattern, Attr)
      +  Tab = element(1, Pattern),
      +  mnesia:dirty_index_match_object(Tab, Pattern, Attr).
       
      -mnesia:write(Record) ->
      -  Tab = element(1, Record),
      -  mnesia:write(Tab, Record, write).
      +mnesia:write(Record) ->
      +  Tab = element(1, Record),
      +  mnesia:write(Tab, Record, write).
       
      -mnesia:s_write(Record) ->
      -  Tab = element(1, Record),
      -  mnesia:write(Tab, Record, sticky_write).
      +mnesia:s_write(Record) ->
      +  Tab = element(1, Record),
      +  mnesia:write(Tab, Record, sticky_write).
       
      -mnesia:delete({Tab, Key}) ->
      -  mnesia:delete(Tab, Key, write).
      +mnesia:delete({Tab, Key}) ->
      +  mnesia:delete(Tab, Key, write).
       
      -mnesia:s_delete({Tab, Key}) ->
      -  mnesia:delete(Tab, Key, sticky_write).
      +mnesia:s_delete({Tab, Key}) ->
      +  mnesia:delete(Tab, Key, sticky_write).
       
      -mnesia:delete_object(Record) ->
      -  Tab = element(1, Record),
      -  mnesia:delete_object(Tab, Record, write).
      +mnesia:delete_object(Record) ->
      +  Tab = element(1, Record),
      +  mnesia:delete_object(Tab, Record, write).
       
      -mnesia:s_delete_object(Record) ->
      -  Tab = element(1, Record),
      -  mnesia:delete_object(Tab, Record, sticky_write).
      +mnesia:s_delete_object(Record) ->
      +  Tab = element(1, Record),
      +  mnesia:delete_object(Tab, Record, sticky_write).
       
      -mnesia:read({Tab, Key}) ->
      -  mnesia:read(Tab, Key, read).
      +mnesia:read({Tab, Key}) ->
      +  mnesia:read(Tab, Key, read).
       
      -mnesia:wread({Tab, Key}) ->
      -  mnesia:read(Tab, Key, write).
      +mnesia:wread({Tab, Key}) ->
      +  mnesia:read(Tab, Key, write).
       
      -mnesia:match_object(Pattern) ->
      -  Tab = element(1, Pattern),
      -  mnesia:match_object(Tab, Pattern, read).
      +mnesia:match_object(Pattern) ->
      +  Tab = element(1, Pattern),
      +  mnesia:match_object(Tab, Pattern, read).
       
      -mnesia:index_match_object(Pattern, Attr) ->
      -  Tab = element(1, Pattern),
      /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap5.xhtml differs (HTML document, ASCII text, with very long lines (1275))
      --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap5.xhtml	2026-08-05 05:56:49.000000000 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap5.xhtml	2026-08-05 05:56:49.000000000 +0000
      @@ -47,9 +47,9 @@
       whether the data resides on the local node or on a remote node.

      Notice that the program runs slower if the data is located on a remote node.

    5. The database can be reconfigured, and tables can be moved between nodes. These operations do not affect the user programs.

    6. It has previously been shown that each table has a number of system attributes, such as index and type.

      Table attributes are specified when the table is created. For example, the -following function creates a table with two RAM replicas:

      mnesia:create_table(foo,
      -                    [{ram_copies, [N1, N2]},
      -                     {attributes, record_info(fields, foo)}]).

      Tables can also have the following properties, where each attribute has a list +following function creates a table with two RAM replicas:

      mnesia:create_table(foo,
      +                    [{ram_copies, [N1, N2]},
      +                     {attributes, record_info(fields, foo)}]).

      Tables can also have the following properties, where each attribute has a list of Erlang nodes as its value:

      • ram_copies. The value of the node list is a list of Erlang nodes, and a RAM replica of the table resides on each node in the list.

        Notice that no disc operations are performed when a program executes write operations to these replicas. However, if permanent RAM replicas are required, @@ -90,52 +90,52 @@ searched for matching records.

        Notice that in ordered_set tables, the records are ordered per fragment, and the order is undefined in results returned by select and match_object, as well as first, next, prev and last.

        The following code illustrates how a Mnesia table is converted to be a -fragmented table and how more fragments are added later:

        Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
        -(a@sam)1> mnesia:start().
        +fragmented table and how more fragments are added later:

        Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
        +(a@sam)1> mnesia:start().
         ok
        -(a@sam)2> mnesia:system_info(running_db_nodes).
        -[b@sam,c@sam,a@sam]
        +(a@sam)2> mnesia:system_info(running_db_nodes).
        +[b@sam,c@sam,a@sam]
         (a@sam)3> Tab = dictionary.
         dictionary
        -(a@sam)4> mnesia:create_table(Tab, [{ram_copies, [a@sam, b@sam]}]).
        -{atomic,ok}
        -(a@sam)5> Write = fun(Keys) -> [mnesia:write({Tab,K,-K}) || K <- Keys], ok end.
        +(a@sam)4> mnesia:create_table(Tab, [{ram_copies, [a@sam, b@sam]}]).
        +{atomic,ok}
        +(a@sam)5> Write = fun(Keys) -> [mnesia:write({Tab,K,-K}) || K <- Keys], ok end.
         #Fun<erl_eval>
        -(a@sam)6> mnesia:activity(sync_dirty, Write, [lists:seq(1, 256)], mnesia_frag).
        +(a@sam)6> mnesia:activity(sync_dirty, Write, [lists:seq(1, 256)], mnesia_frag).
         ok
        -(a@sam)7> mnesia:change_table_frag(Tab, {activate, []}).
        -{atomic,ok}
        -(a@sam)8> mnesia:table_info(Tab, frag_properties).
        -[{base_table,dictionary},
        - {foreign_key,undefined},
        - {hash_module,mnesia_frag_hash},
        - {hash_state,{hash_state,1,1,0,phash2}},
        - {n_fragments,1},
        - {node_pool,[a@sam,b@sam,c@sam]}]
        -(a@sam)9> Info = fun(Item) -> mnesia:table_info(Tab, Item) end.
        +(a@sam)7> mnesia:change_table_frag(Tab, {activate, []}).
        +{atomic,ok}
        +(a@sam)8> mnesia:table_info(Tab, frag_properties).
        +[{base_table,dictionary},
        + {foreign_key,undefined},
        + {hash_module,mnesia_frag_hash},
        + {hash_state,{hash_state,1,1,0,phash2}},
        + {n_fragments,1},
        + {node_pool,[a@sam,b@sam,c@sam]}]
        +(a@sam)9> Info = fun(Item) -> mnesia:table_info(Tab, Item) end.
         #Fun<erl_eval>
        -(a@sam)10> Dist = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
        -[{c@sam,0},{a@sam,1},{b@sam,1}]
        -(a@sam)11> mnesia:change_table_frag(Tab, {add_frag, Dist}).
        -{atomic,ok}
        -(a@sam)12> Dist2 = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
        -[{b@sam,1},{c@sam,1},{a@sam,2}]
        -(a@sam)13> mnesia:change_table_frag(Tab, {add_frag, Dist2}).
        -{atomic,ok}
        -(a@sam)14> Dist3 = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
        -[{a@sam,2},{b@sam,2},{c@sam,2}]
        -(a@sam)15> mnesia:change_table_frag(Tab, {add_frag, Dist3}).
        -{atomic,ok}
        -(a@sam)16> Read = fun(Key) -> mnesia:read({Tab, Key}) end.
        +(a@sam)10> Dist = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
        +[{c@sam,0},{a@sam,1},{b@sam,1}]
        +(a@sam)11> mnesia:change_table_frag(Tab, {add_frag, Dist}).
        +{atomic,ok}
        +(a@sam)12> Dist2 = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
        +[{b@sam,1},{c@sam,1},{a@sam,2}]
        +(a@sam)13> mnesia:change_table_frag(Tab, {add_frag, Dist2}).
        +{atomic,ok}
        +(a@sam)14> Dist3 = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
        +[{a@sam,2},{b@sam,2},{c@sam,2}]
        +(a@sam)15> mnesia:change_table_frag(Tab, {add_frag, Dist3}).
        +{atomic,ok}
        +(a@sam)16> Read = fun(Key) -> mnesia:read({Tab, Key}) end.
         #Fun<erl_eval>
        -(a@sam)17> mnesia:activity(transaction, Read, [12], mnesia_frag).
        -[{dictionary,12,-12}]
        -(a@sam)18> mnesia:activity(sync_dirty, Info, [frag_size], mnesia_frag).
        -[{dictionary,57},
        - {dictionary_frag2,63},
        - {dictionary_frag3,62},
        - {dictionary_frag4,74}]
        -(a@sam)19>

        Fragmentation Properties

        The table property frag_properties can be read with the function +(a@sam)17> mnesia:activity(transaction, Read, [12], mnesia_frag). +[{dictionary,12,-12}] +(a@sam)18> mnesia:activity(sync_dirty, Info, [frag_size], mnesia_frag). +[{dictionary,57}, + {dictionary_frag2,63}, + {dictionary_frag3,62}, + {dictionary_frag4,74}] +(a@sam)19>

        Fragmentation Properties

        The table property frag_properties can be read with the function mnesia:table_info(Tab, frag_properties). The fragmentation properties are a list of tagged tuples with arity 2. By default the list is empty, but when it is non-empty it triggers Mnesia to regard the @@ -171,64 +171,64 @@ This property can explicitly be set at table creation. Default is mnesia_frag_hash.

      • {hash_state, Term} - Enables a table-specific parameterization of a generic hash module. This property can explicitly be set at table creation. -Default is undefined.

        Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
        -(a@sam)1> mnesia:start().
        +Default is undefined.

        Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
        +(a@sam)1> mnesia:start().
         ok
        -(a@sam)2> PrimProps = [{n_fragments, 7}, {node_pool, [node()]}].
        -[{n_fragments,7},{node_pool,[a@sam]}]
        -(a@sam)3> mnesia:create_table(prim_dict,
        -                              [{frag_properties, PrimProps},
        -                               {attributes, [prim_key, prim_val]}]).
        -{atomic,ok}
        -(a@sam)4> SecProps = [{foreign_key, {prim_dict, sec_val}}].
        -[{foreign_key,{prim_dict,sec_val}}]
        -(a@sam)5> mnesia:create_table(sec_dict,
        -                              [{frag_properties, SecProps},
        -                               {attributes, [sec_key, sec_val]}]).
        -{atomic,ok}
        -(a@sam)6> Write = fun(Rec) -> mnesia:write(Rec) end.
        +(a@sam)2> PrimProps = [{n_fragments, 7}, {node_pool, [node()]}].
        +[{n_fragments,7},{node_pool,[a@sam]}]
        +(a@sam)3> mnesia:create_table(prim_dict,
        +                              [{frag_properties, PrimProps},
        +                               {attributes, [prim_key, prim_val]}]).
        +{atomic,ok}
        +(a@sam)4> SecProps = [{foreign_key, {prim_dict, sec_val}}].
        +[{foreign_key,{prim_dict,sec_val}}]
        +(a@sam)5> mnesia:create_table(sec_dict,
        +                              [{frag_properties, SecProps},
        +                               {attributes, [sec_key, sec_val]}]).
        +{atomic,ok}
        +(a@sam)6> Write = fun(Rec) -> mnesia:write(Rec) end.
         #Fun<erl_eval>
         (a@sam)7> PrimKey = 11.
         11
         (a@sam)8> SecKey = 42.
         42
        -(a@sam)9> mnesia:activity(sync_dirty, Write,
        -                          [{prim_dict, PrimKey, -11}], mnesia_frag).
        +(a@sam)9> mnesia:activity(sync_dirty, Write,
        +                          [{prim_dict, PrimKey, -11}], mnesia_frag).
         ok
        -(a@sam)10> mnesia:activity(sync_dirty, Write,
        -                           [{sec_dict, SecKey, PrimKey}], mnesia_frag).
        +(a@sam)10> mnesia:activity(sync_dirty, Write,
        +                           [{sec_dict, SecKey, PrimKey}], mnesia_frag).
         ok
        -(a@sam)11> mnesia:change_table_frag(prim_dict, {add_frag, [node()]}).
        -{atomic,ok}
        -(a@sam)12> SecRead = fun(PrimKey, SecKey) ->
        -               mnesia:read({sec_dict, PrimKey}, SecKey, read) end.
        +(a@sam)11> mnesia:change_table_frag(prim_dict, {add_frag, [node()]}).
        +{atomic,ok}
        +(a@sam)12> SecRead = fun(PrimKey, SecKey) ->
        +               mnesia:read({sec_dict, PrimKey}, SecKey, read) end.
         #Fun<erl_eval>
        -(a@sam)13> mnesia:activity(transaction, SecRead,
        -                           [PrimKey, SecKey], mnesia_frag).
        -[{sec_dict,42,11}]
        -(a@sam)14> Info = fun(Tab, Item) -> mnesia:table_info(Tab, Item) end.
        +(a@sam)13> mnesia:activity(transaction, SecRead,
        +                           [PrimKey, SecKey], mnesia_frag).
        +[{sec_dict,42,11}]
        +(a@sam)14> Info = fun(Tab, Item) -> mnesia:table_info(Tab, Item) end.
         #Fun<erl_eval>
        -(a@sam)15> mnesia:activity(sync_dirty, Info,
        -                           [prim_dict, frag_size], mnesia_frag).
        -[{prim_dict,0},
        - {prim_dict_frag2,0},
        - {prim_dict_frag3,1},
        - {prim_dict_frag4,0},
        - {prim_dict_frag5,0},
        - {prim_dict_frag6,0},
        - {prim_dict_frag7,0},
        - {prim_dict_frag8,0}]
        -(a@sam)16> mnesia:activity(sync_dirty, Info,
        -                           [sec_dict, frag_size], mnesia_frag).
        -[{sec_dict,0},
        - {sec_dict_frag2,0},
        - {sec_dict_frag3,1},
        - {sec_dict_frag4,0},
        - {sec_dict_frag5,0},
        - {sec_dict_frag6,0},
        - {sec_dict_frag7,0},
        - {sec_dict_frag8,0}]
        -(a@sam)17>

      Management of Fragmented Tables

      The function mnesia:change_table_frag(Tab, Change) is intended to be used for +(a@sam)15> mnesia:activity(sync_dirty, Info, + [prim_dict, frag_size], mnesia_frag). +[{prim_dict,0}, + {prim_dict_frag2,0}, /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap7.xhtml differs (HTML document, ASCII text, with very long lines (1110)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap7.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_chap7.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -89,26 +89,26 @@ for starting Mnesia:

      • An Erlang session must be started and a Mnesia directory must be specified for the database.
      • A database schema must be initiated, using the function mnesia:create_schema/1.

      The following example shows how these tasks are performed:

      Step 1: Start an Erlang session and specify a Mnesia directory for the -database:

      % erl -sname klacke -mnesia dir '"/ldisc/scratch/klacke"'
      Erlang/OTP 27 [erts-15.1.2]
      +database:

      % erl -sname klacke -mnesia dir '"/ldisc/scratch/klacke"'
      Erlang/OTP 27 [erts-15.1.2]
       
      -Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
      -(klacke@gin)1> mnesia:create_schema([node()]).
      +Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
      +(klacke@gin)1> mnesia:create_schema([node()]).
       ok
      -(klacke@gin)2>
      +(klacke@gin)2>
       Ctrl+Z
      -[1]+  Stopped                 erl

      Step 2: You can inspect the Mnesia directory to see what files have been +[1]+ Stopped erl

      Step 2: You can inspect the Mnesia directory to see what files have been created:

      % ls -l /ldisc/scratch/klacke
       -rw-rw-r--   1 klacke   staff       247 Aug 12 15:06 FALLBACK.BUP

      The response shows that the file FALLBACK.BUP has been created. This is called a backup file, and it contains an initial schema. If more than one node in the function mnesia:create_schema/1 had been specified, identical backup files -would have been created on all nodes.

      Step 3: Start Mnesia:

      (klacke@gin)3> mnesia:start().
      +would have been created on all nodes.

      Step 3: Start Mnesia:

      (klacke@gin)3> mnesia:start().
       ok

      Step 4: You can see the following listing in the Mnesia directory:

      -rw-rw-r--   1 klacke   staff         86 May 26 19:03 LATEST.LOG
       -rw-rw-r--   1 klacke   staff      34507 May 26 19:03 schema.DAT

      The schema in the backup file FALLBACK.BUP has been used to generate the file schema.DAT. Since there are no other disc resident tables than the schema, no other data files were created. The file FALLBACK.BUP was removed after the successful "restoration". You also see some files that are for internal use by -Mnesia.

      Step 5: Create a table:

      (klacke@gin)4> mnesia:create_table(foo,[{disc_copies, [node()]}]).
      -{atomic,ok}

      Step 6: You can see the following listing in the Mnesia directory:

      % ls -l /ldisc/scratch/klacke
      +Mnesia.

      Step 5: Create a table:

      (klacke@gin)4> mnesia:create_table(foo,[{disc_copies, [node()]}]).
      +{atomic,ok}

      Step 6: You can see the following listing in the Mnesia directory:

      % ls -l /ldisc/scratch/klacke
       -rw-rw-r-- 1 klacke staff    86 May 26 19:07 LATEST.LOG
       -rw-rw-r-- 1 klacke staff    94 May 26 19:07 foo.DCD
       -rw-rw-r-- 1 klacke staff  6679 May 26 19:07 schema.DAT

      The file foo.DCD has been created. This file will eventually store all data @@ -140,11 +140,11 @@ the Mnesia data files. For example, dets contains the function dets:traverse/2, which can be used to view the contents of a Mnesia DAT file. However, this can only be done when Mnesia is not running. So, to view -the schema file, do as follows;

      {ok, N} = dets:open_file(schema, [{file, "./schema.DAT"},{repair,false},
      -{keypos, 2}]),
      -F = fun(X) -> io:format("~p~n", [X]), continue end,
      -dets:traverse(N, F),
      -dets:close(N).

      Warning

      The DAT files must always be opened with option {repair, false}. This +the schema file, do as follows;

      {ok, N} = dets:open_file(schema, [{file, "./schema.DAT"},{repair,false},
      +{keypos, 2}]),
      +F = fun(X) -> io:format("~p~n", [X]), continue end,
      +dets:traverse(N, F),
      +dets:close(N).

      Warning

      The DAT files must always be opened with option {repair, false}. This ensures that these files are not automatically repaired. Without this option, the database can become inconsistent, because Mnesia can believe that the files were properly closed. For information about configuration parameter @@ -348,38 +348,38 @@ located first in the backup.

      The schema itself is a table and is possibly included in the backup. Each node where the schema table resides is regarded as a db_node.

      The following example shows how mnesia:traverse_backup can be used to rename a -db_node in a backup file:

      change_node_name(Mod, From, To, Source, Target) ->
      +db_node in a backup file:

      change_node_name(Mod, From, To, Source, Target) ->
           Switch =
      -        fun(Node) when Node == From -> To;
      -           (Node) when Node == To -> throw({error, already_exists});
      -           (Node) -> Node
      +        fun(Node) when Node == From -> To;
      +           (Node) when Node == To -> throw({error, already_exists});
      +           (Node) -> Node
               end,
           Convert =
      -        fun({schema, version, Version}, Acc) ->
      -                {[{schema, version, Version}], Acc};
      -           ({schema, cookie, Cookie}, Acc) ->
      -                {[{schema, cookie, Cookie}], Acc};
      -           ({schema, Tab, CreateList}, Acc) ->
      -                Keys = [ram_copies, disc_copies, disc_only_copies],
      +        fun({schema, version, Version}, Acc) ->
      +                {[{schema, version, Version}], Acc};
      +           ({schema, cookie, Cookie}, Acc) ->
      +                {[{schema, cookie, Cookie}], Acc};
      +           ({schema, Tab, CreateList}, Acc) ->
      +                Keys = [ram_copies, disc_copies, disc_only_copies],
                       OptSwitch =
      -                    fun({Key, Val}) ->
      -                            case lists:member(Key, Keys) of
      -                                true -> {Key, lists:map(Switch, Val)};
      -                                false-> {Key, Val}
      +                    fun({Key, Val}) ->
      +                            case lists:member(Key, Keys) of
      +                                true -> {Key, lists:map(Switch, Val)};
      +                                false-> {Key, Val}
                                   end
                           end,
      -                {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc};
      -           (Other, Acc) ->
      -                {[Other], Acc}
      +                {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc};
      +           (Other, Acc) ->
      +                {[Other], Acc}
               end,
      -    mnesia:traverse_backup(Source, Mod, Target, Mod, Convert, switched).
      +    mnesia:traverse_backup(Source, Mod, Target, Mod, Convert, switched).
       
      -view(Source, Mod) ->
      -    View = fun(Item, Acc) ->
      -                   io:format("~p.~n",[Item]),
      -                   {[Item], Acc + 1}
      +view(Source, Mod) ->
      +    View = fun(Item, Acc) ->
      +                   io:format("~p.~n",[Item]),
      +                   {[Item], Acc + 1}
                  end,
      -    mnesia:traverse_backup(Source, Mod, dummy, read_only, View, 0).

      Restore

      Tables can be restored online from a backup without restarting Mnesia. A + mnesia:traverse_backup(Source, Mod, dummy, read_only, View, 0).

      Restore

      Tables can be restored online from a backup without restarting Mnesia. A restore is performed with the function mnesia:restore(Opaque, Args), where Args can contain the following tuples:

      • {module, Mod}. The backup module Mod is used to access the backup media. If /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_registry.xhtml differs (HTML document, ASCII text, with very long lines (966)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_registry.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia_registry.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -135,8 +135,8 @@

        Warning

        This function is deprecated. Do not use it.

        A wrapper function for mnesia:create_table/2, which creates a table (if there is no existing table) with an appropriate set of attributes. The attributes and TabDef are forwarded to mnesia:create_table/2. For example, if the table -is to reside as disc_only_copies on all nodes, a call looks as follows:

                  TabDef = [{{disc_only_copies, node()|nodes()]}],
        -          mnesia_registry:create_table(my_reg, TabDef)
        +is to reside as disc_only_copies on all nodes, a call looks as follows:

                  TabDef = [{{disc_only_copies, node()|nodes()]}],
        +          mnesia_registry:create_table(my_reg, TabDef)
      /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia.xhtml differs (HTML document, ASCII text, with very long lines (569)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/mnesia.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -60,11 +60,11 @@ specifies the types of the SNMP keys.

    7. attributes. The names of the attributes for the records that are inserted in the table.

    8. For information about the complete set of table properties and their details, see mnesia:create_table/2.

      This Reference Manual uses a table of persons to illustrate various examples. -The following record definition is assumed:

      -record(person, {name,
      +The following record definition is assumed:

      -record(person, {name,
                        age = 0,
                        address = unknown,
                        salary = 0,
      -                 children = []}),

      The first record attribute is the primary key, or key for short.

      The function descriptions are sorted in alphabetical order. It is recommended to + children = []}),

      The first record attribute is the primary key, or key for short.

      The function descriptions are sorted in alphabetical order. It is recommended to start to read about mnesia:create_table/2, mnesia:lock/2, and mnesia:activity/4 before you continue and learn about the rest.

      Writing or deleting in transaction-context creates a local copy of each modified record during the transaction. During iteration, that is, mnesia:foldl/4, @@ -2852,7 +2852,7 @@ -

      Change the storage type of a table.

      For example:

      mnesia:change_table_copy_type(person, node(), disc_copies)

      Transforms the person table from a RAM table into a disc-based table at +

      Change the storage type of a table.

      For example:

      mnesia:change_table_copy_type(person, node(), disc_copies)

      Transforms the person table from a RAM table into a disc-based table at Node.

      This function can also be used to change the storage type of the table named schema. The schema table can only have ram_copies or disc_copies as the storage type. If the storage type of the schema is ram_copies, no other table @@ -3104,9 +3104,9 @@ back end storage. Backend can currently be ets or dets. Properties is a list of options sent to the back end storage during table creation. Properties cannot contain properties already used by Mnesia, such as type -or named_table.

      For example:

      mnesia:create_table(table, [{ram_copies, [node()]}, {disc_only_copies, nodes()},
      -       {storage_properties,
      -        [{ets, [compressed]}, {dets, [{auto_save, 5000}]} ]}])
    9. {type, Type}, where Type must be either of the atoms set, ordered_set, +or named_table.

      For example:

      mnesia:create_table(table, [{ram_copies, [node()]}, {disc_only_copies, nodes()},
      +       {storage_properties,
      +        [{ets, [compressed]}, {dets, [{auto_save, 5000}]} ]}])
    10. {type, Type}, where Type must be either of the atoms set, ordered_set, or bag. Default is set. In a set, all records have unique keys. In a bag, several records can have the same key, but the record content is unique. If a non-unique record is stored, the old conflicting records are @@ -3119,14 +3119,14 @@ properties for the table. See Fragmentation Properties for details on fragmentation options.

    11. For example, the following call creates the person table (defined earlier) and -replicates it on two nodes:

      mnesia:create_table(person,
      -    [{ram_copies, [N1, N2]},
      -     {attributes, record_info(fields, person)}]).

      If it is required that Mnesia must build and maintain an extra index table on +replicates it on two nodes:

      mnesia:create_table(person,
      +    [{ram_copies, [N1, N2]},
      +     {attributes, record_info(fields, person)}]).

      If it is required that Mnesia must build and maintain an extra index table on attribute address of all the person records that are inserted in the table, -the following code would be issued:

      mnesia:create_table(person,
      -    [{ram_copies, [N1, N2]},
      -     {index, [address]},
      -     {attributes, record_info(fields, person)}]).

      The specification of index and attributes can be hard-coded as +the following code would be issued:

      mnesia:create_table(person,
      +    [{ram_copies, [N1, N2]},
      +     {index, [address]},
      +     {attributes, record_info(fields, person)}]).

      The specification of index and attributes can be hard-coded as {index, [2]} and {attributes, [name, age, address, salary, children]}, respectively.

      mnesia:create_table/2 writes records into the table schema. This function, and all other schema manipulation functions, are implemented with the normal @@ -5441,10 +5441,10 @@ argument. Default is read. The return value depends on MatchSpec.

      Notice that for best performance, select is to be used before any modifying operations are done on that table in the same transaction. That is, do not use write or delete before a select.

      In its simplest forms, the match_spec look as follows:

      • MatchSpec = [MatchFunction]
      • MatchFunction = {MatchHead, [Guard], [Result]}
      • MatchHead = tuple() | record()

      • Guard = {"Guardtest name", ...}
      • Result = "Term construct"

      For a complete description of select, see the ERTS -User's Guide and the ets manual page in STDLIB.

      For example, to find the names of all male persons older than 30 in table Tab:

      MatchHead = #person{name='$1', sex=male, age='$2', _='_'},
      -Guard = {'>', '$2', 30},
      +User's Guide and the ets manual page in STDLIB.

      For example, to find the names of all male persons older than 30 in table Tab:

      MatchHead = #person{name='$1', sex=male, age='$2', _='_'},
      +Guard = {'>', '$2', 30},
       Result = '$1',
      -mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),
      +
      mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),
      @@ -5739,9 +5739,9 @@ specified as a tuple of atoms describing the types. The only significant type is fix_string. This means that a string has a fixed size.

      For example, the following causes table person to be ordered as an SNMP table:

      mnesia:snmp_open_table(person, [{key, string}])

      Consider the following schema for a table of company employees. Each employee is identified by department number and name. The other table column stores the -telephone number:

      mnesia:create_table(employee,
      -    [{snmp, [{key, {integer, string}}]},
      -     {attributes, record_info(fields, employees)}]),

      The corresponding SNMP table would have three columns: department, name, and +telephone number:

      mnesia:create_table(employee,
      +    [{snmp, [{key, {integer, string}}]},
      +     {attributes, record_info(fields, employees)}]),

      The corresponding SNMP table would have three columns: department, name, and telno.

      An option is to have table columns that are not visible through the SNMP protocol. These columns must be the last columns of the table. In the previous example, the SNMP table could have columns department and name only. The @@ -6344,17 +6344,17 @@ transaction is terminated and the function transaction/1 returns the tuple {aborted, Reason}.

      If all is going well, {atomic, ResultOfFun} is returned, where ResultOfFun is the value of the last expression in Fun.

      A function that adds a family to the database can be written as follows if there -is a structure {family, Father, Mother, ChildrenList}:

      add_family({family, F, M, Children}) ->
      -    ChildOids = lists:map(fun oid/1, Children),
      -    Trans = fun() ->
      -        mnesia:write(F#person{children = ChildOids}),
      -        mnesia:write(M#person{children = ChildOids}),
      -        Write = fun(Child) -> mnesia:write(Child) end,
      -        lists:foreach(Write, Children)
      +is a structure {family, Father, Mother, ChildrenList}:

      add_family({family, F, M, Children}) ->
      +    ChildOids = lists:map(fun oid/1, Children),
      +    Trans = fun() ->
      +        mnesia:write(F#person{children = ChildOids}),
      +        mnesia:write(M#person{children = ChildOids}),
      +        Write = fun(Child) -> mnesia:write(Child) end,
      +        lists:foreach(Write, Children)
           end,
      -    mnesia:transaction(Trans).
      +    mnesia:transaction(Trans).
       
      -oid(Rec) -> {element(1, Rec), element(2, Rec)}.

      This code adds a set of people to the database. Running this code within one +oid(Rec) -> {element(1, Rec), element(2, Rec)}.

      This code adds a set of people to the database. Running this code within one transaction ensures that either the whole family is added to the database, or the whole transaction terminates. For example, if the last child is badly formatted, or the executing process terminates because of an 'EXIT' signal @@ -6362,17 +6362,17 @@ where half a family is added can never occur.

      It is also useful to update the database within a transaction if several processes concurrently update the same records. For example, the function raise(Name, Amount), which adds Amount to the salary field of a person, is -to be implemented as follows:

      raise(Name, Amount) ->
      -    mnesia:transaction(fun() ->
      -        case mnesia:wread({person, Name}) of
      -            [P] ->
      +to be implemented as follows:

      raise(Name, Amount) ->
      +    mnesia:transaction(fun() ->
      +        case mnesia:wread({person, Name}) of
      +            [P] ->
                       Salary = Amount + P#person.salary,
      -                P2 = P#person{salary = Salary},
      -                mnesia:write(P2);
      +                P2 = P#person{salary = Salary},
      +                mnesia:write(P2);
                   _ ->
      -                mnesia:abort("No such person")
      +                mnesia:abort("No such person")
               end
      -    end).

      When this function executes within a transaction, several processes running on + end).

      When this function executes within a transaction, several processes running on different nodes can concurrently execute the function raise/2 without interfering with each other.

      Since Mnesia detects deadlocks, a transaction can be restarted any number of times and therefore the Fun shall not have any side effects such as waiting /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/notes.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (6120)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -22,9 +22,9 @@ as all enhancements and bugfixes for every release of Mnesia. Each release of Mnesia thus constitutes one section in this document. The title of each section is the version number of Mnesia.

      Mnesia 4.25.3.1

      Fixed Bugs and Malfunctions

      Mnesia 4.25.3

      Fixed Bugs and Malfunctions

      • Added documentation for user_properties and functions read_table_property/2, write_table_property/2, delete_table_property. -Enhanced documentation for frag_properties.

        Own Id: OTP-20038 Aux Id: GH-10812, PR-10881

      • Fixed a bug where stacktrace was not returned from mnesia:transaction/1 when transaction aborts with an error exception.

        Own Id: OTP-20094 Aux Id: GH-10967, PR-11002

      Mnesia 4.25.2

      Improvements and New Features

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      Mnesia 4.25.1

      Fixed Bugs and Malfunctions

      • Fixed bug where mnesia:del_table_copy/3 could fail when deleting a node that had tables which was not active anywhere.

        Own Id: OTP-19890 Aux Id: ERIERL-1268, PR-10482

      Mnesia 4.25

      Fixed Bugs and Malfunctions

      • Add missing documentation about mnesia:activity/4

        Own Id: OTP-19769 Aux Id: PR-10186

      • With this change mnesia will try to not leak internal messages to user processes.

        Own Id: OTP-19855 Aux Id: GH-10347, PR-10379

      Improvements and New Features

      • The mnesia_registry module will be removed in Erlang/OTP 29.

        Own Id: OTP-19808 Aux Id: PR-10275

      Mnesia 4.24.1

      Fixed Bugs and Malfunctions

      • Mnesia no longer crashes when the node name is used as a table name.

        Own Id: OTP-19745 Aux Id: PR-10147

      Mnesia 4.24

      Improvements and New Features

      • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

        All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

        -type meter() :: integer().
        --type foot() :: integer().

        Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

        -nominal meter() :: integer().
        --nominal foot() :: integer().

        More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

        Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

        Own Id: OTP-19364 Aux Id: PR-9079

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      Mnesia 4.23.5.2

      Fixed Bugs and Malfunctions

      Mnesia 4.23.5.1

      Fixed Bugs and Malfunctions

      • Fixed bug where mnesia:del_table_copy/3 could fail when deleting a node that had tables which was not active anywhere.

        Own Id: OTP-19890 Aux Id: ERIERL-1268, PR-10482

      Mnesia 4.23.5

      Fixed Bugs and Malfunctions

      • With this change mnesia will merge schema of tables using external backends.

        Own Id: OTP-19437 Aux Id: PR-9534

      Mnesia 4.23.4

      Fixed Bugs and Malfunctions

      • Mnesia could fail to load a table, if one of the copy holders was moved during startup.

        Own Id: OTP-19501 Aux Id: ERIERL-1195, PR-9499

      Mnesia 4.23.3

      Fixed Bugs and Malfunctions

      • Mnesia table converted from ext_copies to disc_copies will now be properly saved to disk.

        Own Id: OTP-19292 Aux Id: PR-8921, GH-8706

      • Mnesia could crash if table was deleted during checkpoint initialization.

        Own Id: OTP-19368 Aux Id: ERIERL-1154, PR-9093

      Mnesia 4.23.2

      Fixed Bugs and Malfunctions

      • The mnesia_registry module have been deprecated.

        Own Id: OTP-18994

      Improvements and New Features

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      Mnesia 4.23.1.2

      Fixed Bugs and Malfunctions

      • With this change mnesia will merge schema of tables using external backends.

        Own Id: OTP-19437 Aux Id: PR-9534

      • Mnesia could fail to load a table, if one of the copy holders was moved during startup.

        Own Id: OTP-19501 Aux Id: ERIERL-1195, PR-9499

      Mnesia 4.23.1.1

      Fixed Bugs and Malfunctions

      • Mnesia could crash if table was deleted during checkpoint initialization.

        Own Id: OTP-19368 Aux Id: ERIERL-1154, PR-9093

      Mnesia 4.23.1

      Fixed Bugs and Malfunctions

      • Mnesia could crash during startup if del_table_copy/2 and add_table_copy/3 was invoked when the table was loading.

        Own Id: OTP-19076 Aux Id: ERIERL-1073

      Mnesia 4.23

      Fixed Bugs and Malfunctions

      Mnesia 4.25.2

      Improvements and New Features

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      Mnesia 4.25.1

      Fixed Bugs and Malfunctions

      • Fixed bug where mnesia:del_table_copy/3 could fail when deleting a node that had tables which was not active anywhere.

        Own Id: OTP-19890 Aux Id: ERIERL-1268, PR-10482

      Mnesia 4.25

      Fixed Bugs and Malfunctions

      • Add missing documentation about mnesia:activity/4

        Own Id: OTP-19769 Aux Id: PR-10186

      • With this change mnesia will try to not leak internal messages to user processes.

        Own Id: OTP-19855 Aux Id: GH-10347, PR-10379

      Improvements and New Features

      • The mnesia_registry module will be removed in Erlang/OTP 29.

        Own Id: OTP-19808 Aux Id: PR-10275

      Mnesia 4.24.1

      Fixed Bugs and Malfunctions

      • Mnesia no longer crashes when the node name is used as a table name.

        Own Id: OTP-19745 Aux Id: PR-10147

      Mnesia 4.24

      Improvements and New Features

      • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

        All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

        -type meter() :: integer().
        +-type foot() :: integer().

        Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

        -nominal meter() :: integer().
        +-nominal foot() :: integer().

        More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

        Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

        Own Id: OTP-19364 Aux Id: PR-9079

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      Mnesia 4.23.5.2

      Fixed Bugs and Malfunctions

      Mnesia 4.23.5.1

      Fixed Bugs and Malfunctions

      • Fixed bug where mnesia:del_table_copy/3 could fail when deleting a node that had tables which was not active anywhere.

        Own Id: OTP-19890 Aux Id: ERIERL-1268, PR-10482

      Mnesia 4.23.5

      Fixed Bugs and Malfunctions

      • With this change mnesia will merge schema of tables using external backends.

        Own Id: OTP-19437 Aux Id: PR-9534

      Mnesia 4.23.4

      Fixed Bugs and Malfunctions

      • Mnesia could fail to load a table, if one of the copy holders was moved during startup.

        Own Id: OTP-19501 Aux Id: ERIERL-1195, PR-9499

      Mnesia 4.23.3

      Fixed Bugs and Malfunctions

      • Mnesia table converted from ext_copies to disc_copies will now be properly saved to disk.

        Own Id: OTP-19292 Aux Id: PR-8921, GH-8706

      • Mnesia could crash if table was deleted during checkpoint initialization.

        Own Id: OTP-19368 Aux Id: ERIERL-1154, PR-9093

      Mnesia 4.23.2

      Fixed Bugs and Malfunctions

      • The mnesia_registry module have been deprecated.

        Own Id: OTP-18994

      Improvements and New Features

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      Mnesia 4.23.1.2

      Fixed Bugs and Malfunctions

      • With this change mnesia will merge schema of tables using external backends.

        Own Id: OTP-19437 Aux Id: PR-9534

      • Mnesia could fail to load a table, if one of the copy holders was moved during startup.

        Own Id: OTP-19501 Aux Id: ERIERL-1195, PR-9499

      Mnesia 4.23.1.1

      Fixed Bugs and Malfunctions

      • Mnesia could crash if table was deleted during checkpoint initialization.

        Own Id: OTP-19368 Aux Id: ERIERL-1154, PR-9093

      Mnesia 4.23.1

      Fixed Bugs and Malfunctions

      • Mnesia could crash during startup if del_table_copy/2 and add_table_copy/3 was invoked when the table was loading.

        Own Id: OTP-19076 Aux Id: ERIERL-1073

      Mnesia 4.23

      Fixed Bugs and Malfunctions

      Improvements and New Features

      • Restore recreate of disc_only tables could crash if they had an index.

        Own Id: OTP-18843 Aux Id: GH-7766

      Mnesia 4.22.1

      Fixed Bugs and Malfunctions

      • Do not delete old backup file if the new backup fails.

        Own Id: OTP-18711 Aux Id: ERIERL-963

      Mnesia 4.22

      Improvements and New Features

      • Added debug statistics for active transactions.

        Own Id: OTP-18309 Aux Id: PR-6377

      • The implementation has been fixed to use proc_lib:init_fail/2,3 where appropriate, instead of proc_lib:init_ack/1,2.

        * POTENTIAL INCOMPATIBILITY *

        Own Id: OTP-18490 Aux Id: OTP-18471, GH-6339, PR-6843

      Mnesia 4.21.4.4

      Fixed Bugs and Malfunctions

      • Mnesia could fail to load a table, if one of the copy holders was moved during startup.

        Own Id: OTP-19501 Aux Id: ERIERL-1195, PR-9499

      Mnesia 4.21.4.3

      Fixed Bugs and Malfunctions

      • Mnesia could crash during startup if del_table_copy/2 and add_table_copy/3 was invoked when the table was loading.

        Own Id: OTP-19076 Aux Id: ERIERL-1073

      Mnesia 4.21.4.2

      Fixed Bugs and Malfunctions

      Mnesia 4.21.4.1

      Fixed Bugs and Malfunctions

      • Do not delete old backup file if the new backup fails.

        Own Id: OTP-18711 Aux Id: ERIERL-963

      Mnesia 4.21.4

      Fixed Bugs and Malfunctions

      • Improved consistency for dirty writes when a table was added with /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (751)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.html 2026-08-21 04:00:25.448333981 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia.html 2026-08-21 04:00:25.448333981 +0000 @@ -131,11 +131,11 @@ specifies the types of the SNMP keys.

      • attributes. The names of the attributes for the records that are inserted in the table.

      For information about the complete set of table properties and their details, see mnesia:create_table/2.

      This Reference Manual uses a table of persons to illustrate various examples. -The following record definition is assumed:

      -record(person, {name,
      +The following record definition is assumed:

      -record(person, {name,
                        age = 0,
                        address = unknown,
                        salary = 0,
      -                 children = []}),

      The first record attribute is the primary key, or key for short.

      The function descriptions are sorted in alphabetical order. It is recommended to + children = []}),

      The first record attribute is the primary key, or key for short.

      The function descriptions are sorted in alphabetical order. It is recommended to start to read about mnesia:create_table/2, mnesia:lock/2, and mnesia:activity/4 before you continue and learn about the rest.

      Writing or deleting in transaction-context creates a local copy of each modified record during the transaction. During iteration, that is, mnesia:foldl/4, @@ -2939,7 +2939,7 @@ -

      Change the storage type of a table.

      For example:

      mnesia:change_table_copy_type(person, node(), disc_copies)

      Transforms the person table from a RAM table into a disc-based table at +

      Change the storage type of a table.

      For example:

      mnesia:change_table_copy_type(person, node(), disc_copies)

      Transforms the person table from a RAM table into a disc-based table at Node.

      This function can also be used to change the storage type of the table named schema. The schema table can only have ram_copies or disc_copies as the storage type. If the storage type of the schema is ram_copies, no other table @@ -3191,9 +3191,9 @@ back end storage. Backend can currently be ets or dets. Properties is a list of options sent to the back end storage during table creation. Properties cannot contain properties already used by Mnesia, such as type -or named_table.

      For example:

      mnesia:create_table(table, [{ram_copies, [node()]}, {disc_only_copies, nodes()},
      -       {storage_properties,
      -        [{ets, [compressed]}, {dets, [{auto_save, 5000}]} ]}])
    12. {type, Type}, where Type must be either of the atoms set, ordered_set, +or named_table.

      For example:

      mnesia:create_table(table, [{ram_copies, [node()]}, {disc_only_copies, nodes()},
      +       {storage_properties,
      +        [{ets, [compressed]}, {dets, [{auto_save, 5000}]} ]}])
    13. {type, Type}, where Type must be either of the atoms set, ordered_set, or bag. Default is set. In a set, all records have unique keys. In a bag, several records can have the same key, but the record content is unique. If a non-unique record is stored, the old conflicting records are @@ -3206,14 +3206,14 @@ properties for the table. See Fragmentation Properties for details on fragmentation options.

    14. For example, the following call creates the person table (defined earlier) and -replicates it on two nodes:

      mnesia:create_table(person,
      -    [{ram_copies, [N1, N2]},
      -     {attributes, record_info(fields, person)}]).

      If it is required that Mnesia must build and maintain an extra index table on +replicates it on two nodes:

      mnesia:create_table(person,
      +    [{ram_copies, [N1, N2]},
      +     {attributes, record_info(fields, person)}]).

      If it is required that Mnesia must build and maintain an extra index table on attribute address of all the person records that are inserted in the table, -the following code would be issued:

      mnesia:create_table(person,
      -    [{ram_copies, [N1, N2]},
      -     {index, [address]},
      -     {attributes, record_info(fields, person)}]).

      The specification of index and attributes can be hard-coded as +the following code would be issued:

      mnesia:create_table(person,
      +    [{ram_copies, [N1, N2]},
      +     {index, [address]},
      +     {attributes, record_info(fields, person)}]).

      The specification of index and attributes can be hard-coded as {index, [2]} and {attributes, [name, age, address, salary, children]}, respectively.

      mnesia:create_table/2 writes records into the table schema. This function, and all other schema manipulation functions, are implemented with the normal @@ -5528,10 +5528,10 @@ argument. Default is read. The return value depends on MatchSpec.

      Notice that for best performance, select is to be used before any modifying operations are done on that table in the same transaction. That is, do not use write or delete before a select.

      In its simplest forms, the match_spec look as follows:

      • MatchSpec = [MatchFunction]
      • MatchFunction = {MatchHead, [Guard], [Result]}
      • MatchHead = tuple() | record()

      • Guard = {"Guardtest name", ...}
      • Result = "Term construct"

      For a complete description of select, see the ERTS -User's Guide and the ets manual page in STDLIB.

      For example, to find the names of all male persons older than 30 in table Tab:

      MatchHead = #href_anchor"ss">person{name='$1', sex=male, age='$2', _='_'},
      -Guard = {'>', '$2', 30},
      +User's Guide and the ets manual page in STDLIB.

      For example, to find the names of all male persons older than 30 in table Tab:

      MatchHead = #href_anchor"ss">person{name='$1', sex=male, age='$2', _='_'},
      +Guard = {'>', '$2', 30},
       Result = '$1',
      -mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),
      +
      mnesia:select(Tab,[{MatchHead, [Guard], [Result]}]),
      @@ -5826,9 +5826,9 @@ specified as a tuple of atoms describing the types. The only significant type is fix_string. This means that a string has a fixed size.

      For example, the following causes table person to be ordered as an SNMP table:

      mnesia:snmp_open_table(person, [{key, string}])

      Consider the following schema for a table of company employees. Each employee is identified by department number and name. The other table column stores the -telephone number:

      mnesia:create_table(employee,
      -    [{snmp, [{key, {integer, string}}]},
      -     {attributes, record_info(fields, employees)}]),

      The corresponding SNMP table would have three columns: department, name, and +telephone number:

      mnesia:create_table(employee,
      +    [{snmp, [{key, {integer, string}}]},
      +     {attributes, record_info(fields, employees)}]),

      The corresponding SNMP table would have three columns: department, name, and telno.

      An option is to have table columns that are not visible through the SNMP protocol. These columns must be the last columns of the table. In the previous example, the SNMP table could have columns department and name only. The @@ -6431,17 +6431,17 @@ transaction is terminated and the function transaction/1 returns the tuple {aborted, Reason}.

      If all is going well, {atomic, ResultOfFun} is returned, where ResultOfFun is the value of the last expression in Fun.

      A function that adds a family to the database can be written as follows if there -is a structure {family, Father, Mother, ChildrenList}:

      add_family({family, F, M, Children}) ->
      -    ChildOids = lists:map(fun oid/1, Children),
      -    Trans = fun() ->
      -        mnesia:write(F#person{children = ChildOids}),
      -        mnesia:write(M#person{children = ChildOids}),
      -        Write = fun(Child) -> mnesia:write(Child) end,
      -        lists:foreach(Write, Children)
      +is a structure {family, Father, Mother, ChildrenList}:

      add_family({family, F, M, Children}) ->
      +    ChildOids = lists:map(fun oid/1, Children),
      +    Trans = fun() ->
      +        mnesia:write(F#person{children = ChildOids}),
      +        mnesia:write(M#person{children = ChildOids}),
      +        Write = fun(Child) -> mnesia:write(Child) end,
      +        lists:foreach(Write, Children)
           end,
      -    mnesia:transaction(Trans).
      +    mnesia:transaction(Trans).
       
      -oid(Rec) -> {element(1, Rec), element(2, Rec)}.

      This code adds a set of people to the database. Running this code within one +oid(Rec) -> {element(1, Rec), element(2, Rec)}.

      This code adds a set of people to the database. Running this code within one transaction ensures that either the whole family is added to the database, or the whole transaction terminates. For example, if the last child is badly formatted, or the executing process terminates because of an 'EXIT' signal @@ -6449,17 +6449,17 @@ where half a family is added can never occur.

      It is also useful to update the database within a transaction if several processes concurrently update the same records. For example, the function raise(Name, Amount), which adds Amount to the salary field of a person, is -to be implemented as follows:

      raise(Name, Amount) ->
      -    mnesia:transaction(fun() ->
      -        case mnesia:wread({person, Name}) of
      -            [P] ->
      +to be implemented as follows:

      raise(Name, Amount) ->
      +    mnesia:transaction(fun() ->
      +        case mnesia:wread({person, Name}) of
      +            [P] ->
                       Salary = Amount + P#person.salary,
      -                P2 = P#person{salary = Salary},
      -                mnesia:write(P2);
      +                P2 = P#person{salary = Salary},
      +                mnesia:write(P2);
                   _ ->
      -                mnesia:abort("No such person")
      +                mnesia:abort("No such person")
               end
      -    end).

      When this function executes within a transaction, several processes running on + end).

      When this function executes within a transaction, several processes running on different nodes can concurrently execute the function raise/2 without interfering with each other.

      Since Mnesia detects deadlocks, a transaction can be restarted any number of times and therefore the Fun shall not have any side effects such as waiting /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_a.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (894)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_a.html 2026-08-21 04:00:25.470334125 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_a.html 2026-08-21 04:00:25.472334138 +0000 @@ -117,11 +117,11 @@ %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --module(mnesia_backup). +-module(mnesia_backup). --include_lib("kernel/include/file.hrl"). +-include_lib("kernel/include/file.hrl"). --export([ +-export([ %% Write access open_write/1, write/2, @@ -132,105 +132,105 @@ open_read/1, read/1, close_read/1 - ]). + ]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Backup callback interface --record(backup, {tmp_file, file, file_desc}). +-record(backup, {tmp_file, file, file_desc}). %% Opens backup media for write %% %% Returns {ok, OpaqueData} or {error, Reason} -open_write(OpaqueData) -> +open_write(OpaqueData) -> File = OpaqueData, - Tmp = lists:concat([File,".BUPTMP"]), - file:delete(Tmp), - case disk_log:open([{name, make_ref()}, - {file, Tmp}, - {repair, false}, - {linkto, self()}]) of - {ok, Fd} -> - {ok, #backup{tmp_file = Tmp, file = File, file_desc = Fd}}; - {error, Reason} -> - {error, Reason} + Tmp = lists:concat([File,".BUPTMP"]), + file:delete(Tmp), + case disk_log:open([{name, make_ref()}, + {file, Tmp}, + {repair, false}, + {linkto, self()}]) of + {ok, Fd} -> + {ok, #backup{tmp_file = Tmp, file = File, file_desc = Fd}}; + {error, Reason} -> + {error, Reason} end. %% Writes BackupItems to the backup media %% %% Returns {ok, OpaqueData} or {error, Reason} -write(OpaqueData, BackupItems) -> +write(OpaqueData, BackupItems) -> B = OpaqueData, - case disk_log:log_terms(B#backup.file_desc, BackupItems) of + case disk_log:log_terms(B#backup.file_desc, BackupItems) of ok -> - {ok, B}; - {error, Reason} -> - abort_write(B), - {error, Reason} + {ok, B}; + {error, Reason} -> + abort_write(B), + {error, Reason} end. %% Closes the backup media after a successful backup %% %% Returns {ok, ReturnValueToUser} or {error, Reason} -commit_write(OpaqueData) -> +commit_write(OpaqueData) -> B = OpaqueData, - case disk_log:sync(B#backup.file_desc) of + case disk_log:sync(B#backup.file_desc) of ok -> - case disk_log:close(B#backup.file_desc) of + case disk_log:close(B#backup.file_desc) of ok -> - file:delete(B#backup.file), - case file:rename(B#backup.tmp_file, B#backup.file) of + file:delete(B#backup.file), + case file:rename(B#backup.tmp_file, B#backup.file) of ok -> - {ok, B#backup.file}; - {error, Reason} -> - {error, Reason} + {ok, B#backup.file}; + {error, Reason} -> + {error, Reason} end; - {error, Reason} -> - {error, Reason} + {error, Reason} -> + {error, Reason} end; - {error, Reason} -> - {error, Reason} + {error, Reason} -> + {error, Reason} end. %% Closes the backup media after an interrupted backup %% %% Returns {ok, ReturnValueToUser} or {error, Reason} -abort_write(BackupRef) -> - Res = disk_log:close(BackupRef#backup.file_desc), - file:delete(BackupRef#backup.tmp_file), +abort_write(BackupRef) -> + Res = disk_log:close(BackupRef#backup.file_desc), + file:delete(BackupRef#backup.tmp_file), case Res of ok -> - {ok, BackupRef#backup.file}; - {error, Reason} -> - {error, Reason} + {ok, BackupRef#backup.file}; + {error, Reason} -> + {error, Reason} end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Restore callback interface --record(restore, {file, file_desc, cont}). +-record(restore, {file, file_desc, cont}). %% Opens backup media for read %% %% Returns {ok, OpaqueData} or {error, Reason} -open_read(OpaqueData) -> +open_read(OpaqueData) -> File = OpaqueData, - case file:read_file_info(File) of - {error, Reason} -> - {error, Reason}; + case file:read_file_info(File) of + {error, Reason} -> + {error, Reason}; _FileInfo -> %% file exists - case disk_log:open([{file, File}, - {name, make_ref()}, - {repair, false}, - {mode, read_only}, - {linkto, self()}]) of - {ok, Fd} -> - {ok, #restore{file = File, file_desc = Fd, cont = start}}; - {repaired, Fd, _, {badbytes, 0}} -> - {ok, #restore{file = File, file_desc = Fd, cont = start}}; - {repaired, Fd, _, _} -> - {ok, #restore{file = File, file_desc = Fd, cont = start}}; - {error, Reason} -> - {error, Reason} + case disk_log:open([{file, File}, + {name, make_ref()}, + {repair, false}, + {mode, read_only}, + {linkto, self()}]) of + {ok, Fd} -> + {ok, #restore{file = File, file_desc = Fd, cont = start}}; + {repaired, Fd, _, {badbytes, 0}} -> + {ok, #restore{file = File, file_desc = Fd, cont = start}}; + {repaired, Fd, _, _} -> + {ok, #restore{file = File, file_desc = Fd, cont = start}}; + {error, Reason} -> + {error, Reason} end end. @@ -239,30 +239,30 @@ %% Returns {ok, OpaqueData, BackupItems} or {error, Reason} %% %% BackupItems == [] is interpreted as eof -read(OpaqueData) -> +read(OpaqueData) -> R = OpaqueData, Fd = R#restore.file_desc, - case disk_log:chunk(Fd, R#restore.cont) of - {error, Reason} -> - {error, {"Possibly truncated", Reason}}; + case disk_log:chunk(Fd, R#restore.cont) of + {error, Reason} -> + {error, {"Possibly truncated", Reason}}; eof -> - {ok, R, []}; - {Cont, []} -> - read(R#restore{cont = Cont}); - {Cont, BackupItems, _BadBytes} -> - {ok, R#restore{cont = Cont}, BackupItems}; - {Cont, BackupItems} -> - {ok, R#restore{cont = Cont}, BackupItems} /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_b.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1047)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_b.html 2026-08-21 04:00:25.495334287 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_b.html 2026-08-21 04:00:25.495334287 +0000 @@ -89,10 +89,10 @@ -

      mnesia_access Callback Behavior

      -module(mnesia_frag).
      +

      mnesia_access Callback Behavior

      -module(mnesia_frag).
       
       %% Callback functions when accessed within an activity
      --export([
      +-export([
                lock/4,
                write/5, delete/5, delete_object/5,
                read/5, match_object/5, all_keys/4,
      @@ -101,242 +101,242 @@
                foldl/6, foldr/6, table_info/4,
                first/3, next/4, prev/4, last/3,
                clear_table/4
      -        ]).
      +        ]).
       
       %% Callback functions which provides transparent
       %% access of fragmented tables from any activity
       %% access context.
       
      -lock(ActivityId, Opaque, {table , Tab}, LockKind) ->
      -    case frag_names(Tab) of
      -        [Tab] ->
      -            mnesia:lock(ActivityId, Opaque, {table, Tab}, LockKind);
      +lock(ActivityId, Opaque, {table , Tab}, LockKind) ->
      +    case frag_names(Tab) of
      +        [Tab] ->
      +            mnesia:lock(ActivityId, Opaque, {table, Tab}, LockKind);
               Frags ->
      -            DeepNs = [mnesia:lock(ActivityId, Opaque, {table, F}, LockKind) ||
      -                         F <- Frags],
      -            mnesia_lib:uniq(lists:append(DeepNs))
      +            DeepNs = [mnesia:lock(ActivityId, Opaque, {table, F}, LockKind) ||
      +                         F <- Frags],
      +            mnesia_lib:uniq(lists:append(DeepNs))
           end;
       
      -lock(ActivityId, Opaque, LockItem, LockKind) ->
      -    mnesia:lock(ActivityId, Opaque, LockItem, LockKind).
      +lock(ActivityId, Opaque, LockItem, LockKind) ->
      +    mnesia:lock(ActivityId, Opaque, LockItem, LockKind).
       
      -write(ActivityId, Opaque, Tab, Rec, LockKind) ->
      -    Frag = record_to_frag_name(Tab, Rec),
      -    mnesia:write(ActivityId, Opaque, Frag, Rec, LockKind).
      -
      -delete(ActivityId, Opaque, Tab, Key, LockKind) ->
      -    Frag = key_to_frag_name(Tab, Key),
      -    mnesia:delete(ActivityId, Opaque, Frag, Key, LockKind).
      -
      -delete_object(ActivityId, Opaque, Tab, Rec, LockKind) ->
      -    Frag = record_to_frag_name(Tab, Rec),
      -    mnesia:delete_object(ActivityId, Opaque, Frag, Rec, LockKind).
      -
      -read(ActivityId, Opaque, Tab, Key, LockKind) ->
      -    Frag = key_to_frag_name(Tab, Key),
      -    mnesia:read(ActivityId, Opaque, Frag, Key, LockKind).
      -
      -match_object(ActivityId, Opaque, Tab, HeadPat, LockKind) ->
      -    MatchSpec = [{HeadPat, [], ['$_']}],
      -    select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
      -
      -select(ActivityId, Opaque, Tab, MatchSpec, LockKind) ->
      -    do_select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
      -
      -
      -select(ActivityId, Opaque, Tab, MatchSpec, Limit, LockKind) ->
      -    init_select(ActivityId, Opaque, Tab, MatchSpec, Limit, LockKind).
      -
      -select_cont(_Tid,_,{frag_cont, '$end_of_table', [],_}) -> '$end_of_table';
      -select_cont(Tid,Ts,{frag_cont, '$end_of_table', [{Tab,Node,Type}|Rest],Args}) ->
      -    {Spec,LockKind,Limit} = Args,
      -    InitFun = fun(FixedSpec) -> mnesia:dirty_sel_init(Node,Tab,FixedSpec,Limit,Type) end,
      -    Res = mnesia:fun_select(Tid,Ts,Tab,Spec,LockKind,Tab,InitFun,Limit,Node,Type),
      -    frag_sel_cont(Res, Rest, Args);
      -select_cont(Tid,Ts,{frag_cont, Cont, TabL, Args}) ->
      -    frag_sel_cont(mnesia:select_cont(Tid,Ts,Cont),TabL,Args);
      -select_cont(Tid,Ts,Else) ->
      -    mnesia:select_cont(Tid,Ts,Else).
      -
      -all_keys(ActivityId, Opaque, Tab, LockKind) ->
      -    Match = [mnesia:all_keys(ActivityId, Opaque, Frag, LockKind)
      -             || Frag <- frag_names(Tab)],
      -    lists:append(Match).
      +write(ActivityId, Opaque, Tab, Rec, LockKind) ->
      +    Frag = record_to_frag_name(Tab, Rec),
      +    mnesia:write(ActivityId, Opaque, Frag, Rec, LockKind).
      +
      +delete(ActivityId, Opaque, Tab, Key, LockKind) ->
      +    Frag = key_to_frag_name(Tab, Key),
      +    mnesia:delete(ActivityId, Opaque, Frag, Key, LockKind).
      +
      +delete_object(ActivityId, Opaque, Tab, Rec, LockKind) ->
      +    Frag = record_to_frag_name(Tab, Rec),
      +    mnesia:delete_object(ActivityId, Opaque, Frag, Rec, LockKind).
      +
      +read(ActivityId, Opaque, Tab, Key, LockKind) ->
      +    Frag = key_to_frag_name(Tab, Key),
      +    mnesia:read(ActivityId, Opaque, Frag, Key, LockKind).
      +
      +match_object(ActivityId, Opaque, Tab, HeadPat, LockKind) ->
      +    MatchSpec = [{HeadPat, [], ['$_']}],
      +    select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
      +
      +select(ActivityId, Opaque, Tab, MatchSpec, LockKind) ->
      +    do_select(ActivityId, Opaque, Tab, MatchSpec, LockKind).
      +
      +
      +select(ActivityId, Opaque, Tab, MatchSpec, Limit, LockKind) ->
      +    init_select(ActivityId, Opaque, Tab, MatchSpec, Limit, LockKind).
      +
      +select_cont(_Tid,_,{frag_cont, '$end_of_table', [],_}) -> '$end_of_table';
      +select_cont(Tid,Ts,{frag_cont, '$end_of_table', [{Tab,Node,Type}|Rest],Args}) ->
      +    {Spec,LockKind,Limit} = Args,
      +    InitFun = fun(FixedSpec) -> mnesia:dirty_sel_init(Node,Tab,FixedSpec,Limit,Type) end,
      +    Res = mnesia:fun_select(Tid,Ts,Tab,Spec,LockKind,Tab,InitFun,Limit,Node,Type),
      +    frag_sel_cont(Res, Rest, Args);
      +select_cont(Tid,Ts,{frag_cont, Cont, TabL, Args}) ->
      +    frag_sel_cont(mnesia:select_cont(Tid,Ts,Cont),TabL,Args);
      +select_cont(Tid,Ts,Else) ->
      +    mnesia:select_cont(Tid,Ts,Else).
      +
      +all_keys(ActivityId, Opaque, Tab, LockKind) ->
      +    Match = [mnesia:all_keys(ActivityId, Opaque, Frag, LockKind)
      +             || Frag <- frag_names(Tab)],
      +    lists:append(Match).
       
      -clear_table(ActivityId, Opaque, Tab, Obj) ->
      -    [mnesia:clear_table(ActivityId, Opaque, Frag, Obj)  || Frag <- frag_names(Tab)],
      +clear_table(ActivityId, Opaque, Tab, Obj) ->
      +    [mnesia:clear_table(ActivityId, Opaque, Frag, Obj)  || Frag <- frag_names(Tab)],
           ok.
       
      -index_match_object(ActivityId, Opaque, Tab, Pat, Attr, LockKind) ->
      +index_match_object(ActivityId, Opaque, Tab, Pat, Attr, LockKind) ->
           Match =
      -        [mnesia:index_match_object(ActivityId, Opaque, Frag, Pat, Attr, LockKind)
      -         || Frag <- frag_names(Tab)],
      -    lists:append(Match).
      +        [mnesia:index_match_object(ActivityId, Opaque, Frag, Pat, Attr, LockKind)
      +         || Frag <- frag_names(Tab)],
      +    lists:append(Match).
       
      -index_read(ActivityId, Opaque, Tab, Key, Attr, LockKind) ->
      +index_read(ActivityId, Opaque, Tab, Key, Attr, LockKind) ->
           Match =
      -        [mnesia:index_read(ActivityId, Opaque, Frag, Key, Attr, LockKind)
      -         || Frag <- frag_names(Tab)],
      -    lists:append(Match).
      -
      -foldl(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
      -    Fun2 = fun(Frag, A) ->
      -                   mnesia:foldl(ActivityId, Opaque, Fun, A, Frag, LockKind)
      +        [mnesia:index_read(ActivityId, Opaque, Frag, Key, Attr, LockKind)
      +         || Frag <- frag_names(Tab)],
      +    lists:append(Match).
      +
      +foldl(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
      +    Fun2 = fun(Frag, A) ->
      +                   mnesia:foldl(ActivityId, Opaque, Fun, A, Frag, LockKind)
                  end,
      -    lists:foldl(Fun2, Acc, frag_names(Tab)).
      +    lists:foldl(Fun2, Acc, frag_names(Tab)).
       
      -foldr(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
      -    Fun2 = fun(Frag, A) ->
      -                   mnesia:foldr(ActivityId, Opaque, Fun, A, Frag, LockKind)
      +foldr(ActivityId, Opaque, Fun, Acc, Tab, LockKind) ->
      +    Fun2 = fun(Frag, A) ->
      +                   mnesia:foldr(ActivityId, Opaque, Fun, A, Frag, LockKind)
                  end,
      -    lists:foldr(Fun2, Acc, frag_names(Tab)).
      +    lists:foldr(Fun2, Acc, frag_names(Tab)).
       
      -table_info(ActivityId, Opaque, {Tab, Key}, Item) ->
      -    Frag = key_to_frag_name(Tab, Key),
      -    table_info2(ActivityId, Opaque, Tab, Frag, Item);
      -table_info(ActivityId, Opaque, Tab, Item) ->
      -    table_info2(ActivityId, Opaque, Tab, Tab, Item).
      +table_info(ActivityId, Opaque, {Tab, Key}, Item) ->
      +    Frag = key_to_frag_name(Tab, Key),
      +    table_info2(ActivityId, Opaque, Tab, Frag, Item);
      +table_info(ActivityId, Opaque, Tab, Item) ->
      +    table_info2(ActivityId, Opaque, Tab, Tab, Item).
       
      -table_info2(ActivityId, Opaque, Tab, Frag, Item) ->
      +table_info2(ActivityId, Opaque, Tab, Frag, Item) ->
           case Item of
               size ->
      -            SumFun = fun({_, Size}, Acc) -> Acc + Size end,
      -            lists:foldl(SumFun, 0, frag_size(ActivityId, Opaque, Tab));
      +            SumFun = fun({_, Size}, Acc) -> Acc + Size end,
      +            lists:foldl(SumFun, 0, frag_size(ActivityId, Opaque, Tab));
               memory ->
      /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_c.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1038))
      --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_c.html	2026-08-21 04:00:25.515334417 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_app_c.html	2026-08-21 04:00:25.515334417 +0000
      @@ -89,140 +89,140 @@
         
       
       
      -

      mnesia_frag_hash Callback Behavior

      -module(mnesia_frag_hash).
      --compile([{nowarn_deprecated_function, [{erlang,phash,2}]}]).
      +

      mnesia_frag_hash Callback Behavior

      -module(mnesia_frag_hash).
      +-compile([{nowarn_deprecated_function, [{erlang,phash,2}]}]).
       
       %% Fragmented Table Hashing callback functions
      --export([
      +-export([
                init_state/2,
                add_frag/1,
                del_frag/1,
                key_to_frag_number/2,
                match_spec_to_frag_numbers/2
      -        ]).
      -record(hash_state,
      -    {n_fragments,
      +        ]).
      -record(hash_state,
      +    {n_fragments,
            next_n_to_split,
            n_doubles,
      -     function}).
      +     function}).
       
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      --spec init_state(Tab, State) -> NewState when
      -      Tab :: atom(),
      -      State :: term(),
      -      NewState :: term().
      -init_state(_Tab, State) when State == undefined ->
      -    #hash_state{n_fragments     = 1,
      +-spec init_state(Tab, State) -> NewState when
      +      Tab :: atom(),
      +      State :: term(),
      +      NewState :: term().
      +init_state(_Tab, State) when State == undefined ->
      +    #hash_state{n_fragments     = 1,
                       next_n_to_split = 1,
                       n_doubles       = 0,
      -                function        = phash2}.
      +                function        = phash2}.
       
      -convert_old_state({hash_state, N, P, L}) ->
      -    #hash_state{n_fragments     = N,
      +convert_old_state({hash_state, N, P, L}) ->
      +    #hash_state{n_fragments     = N,
                       next_n_to_split = P,
                       n_doubles       = L,
      -                function        = phash}.
      +                function        = phash}.
       
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       
      --spec add_frag(State :: term()) -> {NewState, IterFrags, AdditionalLockFrags} when
      -      NewState :: term(),
      -      IterFrags :: [integer()],
      -      AdditionalLockFrags :: [integer()].
      -add_frag(#hash_state{next_n_to_split = SplitN, n_doubles = L, n_fragments = N} = State) ->
      +-spec add_frag(State :: term()) -> {NewState, IterFrags, AdditionalLockFrags} when
      +      NewState :: term(),
      +      IterFrags :: [integer()],
      +      AdditionalLockFrags :: [integer()].
      +add_frag(#hash_state{next_n_to_split = SplitN, n_doubles = L, n_fragments = N} = State) ->
           P = SplitN + 1,
           NewN = N + 1,
      -    State2 = case power2(L) + 1 of
      +    State2 = case power2(L) + 1 of
               P2 when P2 == P ->
      -            State#hash_state{n_fragments      = NewN,
      +            State#hash_state{n_fragments      = NewN,
                                    n_doubles        = L + 1,
      -                             next_n_to_split  = 1};
      +                             next_n_to_split  = 1};
               _ ->
      -            State#hash_state{n_fragments     = NewN,
      -                             next_n_to_split = P}
      +            State#hash_state{n_fragments     = NewN,
      +                             next_n_to_split = P}
           end,
      -    {State2, [SplitN], [NewN]};
      -add_frag(OldState) ->
      -    State = convert_old_state(OldState),
      -    add_frag(State).
      +    {State2, [SplitN], [NewN]};
      +add_frag(OldState) ->
      +    State = convert_old_state(OldState),
      +    add_frag(State).
       
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       
      --spec del_frag(State :: term()) -> {NewState, IterFrags, AdditionalLockFrags} when
      -      NewState :: term(),
      -      IterFrags :: [integer()],
      -      AdditionalLockFrags :: [integer()].
      -del_frag(#hash_state{next_n_to_split = SplitN, n_doubles = L, n_fragments = N} = State) ->
      +-spec del_frag(State :: term()) -> {NewState, IterFrags, AdditionalLockFrags} when
      +      NewState :: term(),
      +      IterFrags :: [integer()],
      +      AdditionalLockFrags :: [integer()].
      +del_frag(#hash_state{next_n_to_split = SplitN, n_doubles = L, n_fragments = N} = State) ->
           P = SplitN - 1,
           if
               P < 1 ->
                   L2 = L - 1,
      -            MergeN = power2(L2),
      -            State2 = State#hash_state{n_fragments     = N - 1,
      +            MergeN = power2(L2),
      +            State2 = State#hash_state{n_fragments     = N - 1,
                                             next_n_to_split = MergeN,
      -                                      n_doubles       = L2},
      -            {State2, [N], [MergeN]};
      +                                      n_doubles       = L2},
      +            {State2, [N], [MergeN]};
               true ->
                   MergeN = P,
      -            State2 = State#hash_state{n_fragments     = N - 1,
      -                                      next_n_to_split = MergeN},
      -            {State2, [N], [MergeN]}
      +            State2 = State#hash_state{n_fragments     = N - 1,
      +                                      next_n_to_split = MergeN},
      +            {State2, [N], [MergeN]}
           end;
      -del_frag(OldState) ->
      -    State = convert_old_state(OldState),
      -    del_frag(State).
      +del_frag(OldState) ->
      +    State = convert_old_state(OldState),
      +    del_frag(State).
       
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      --spec key_to_frag_number(State, Key) -> Fragnum when
      -      State :: term(),
      -      Key :: term(),
      -      Fragnum :: integer().
      -key_to_frag_number(#hash_state{function = phash, n_fragments = N, n_doubles = L}, Key) ->
      -    A = erlang:phash(Key, power2(L + 1)),
      +-spec key_to_frag_number(State, Key) -> Fragnum when
      +      State :: term(),
      +      Key :: term(),
      +      Fragnum :: integer().
      +key_to_frag_number(#hash_state{function = phash, n_fragments = N, n_doubles = L}, Key) ->
      +    A = erlang:phash(Key, power2(L + 1)),
           if
               A > N ->
      -            A - power2(L);
      +            A - power2(L);
               true ->
                   A
           end;
      -key_to_frag_number(#hash_state{function = phash2, n_fragments = N, n_doubles = L}, Key) ->
      -    A = erlang:phash2(Key, power2(L + 1)) + 1,
      +key_to_frag_number(#hash_state{function = phash2, n_fragments = N, n_doubles = L}, Key) ->
      +    A = erlang:phash2(Key, power2(L + 1)) + 1,
           if
               A > N ->
      -            A - power2(L);
      +            A - power2(L);
               true ->
                   A
           end;
      -key_to_frag_number(OldState, Key) ->
      -    State = convert_old_state(OldState),
      -    key_to_frag_number(State, Key).
      +key_to_frag_number(OldState, Key) ->
      +    State = convert_old_state(OldState),
      +    key_to_frag_number(State, Key).
       
       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      --spec match_spec_to_frag_numbers(State, MatchSpec) -> Fragnums when
      -      State :: term(),
      -      MatchSpec :: ets:match_spec(),
      -      Fragnums :: [integer()].
      -match_spec_to_frag_numbers(#hash_state{n_fragments = N} = State, MatchSpec) ->
      +-spec match_spec_to_frag_numbers(State, MatchSpec) -> Fragnums when
      +      State :: term(),
      +      MatchSpec :: ets:match_spec(),
      +      Fragnums :: [integer()].
      +match_spec_to_frag_numbers(#hash_state{n_fragments = N} = State, MatchSpec) ->
           case MatchSpec of
      -        [{HeadPat, _, _}] when is_tuple(HeadPat), tuple_size(HeadPat) > 2 ->
      -            KeyPat = element(2, HeadPat),
      -            case has_var(KeyPat) of
      +        [{HeadPat, _, _}] when is_tuple(HeadPat), tuple_size(HeadPat) > 2 ->
      +            KeyPat = element(2, HeadPat),
      +            case has_var(KeyPat) of
                       false ->
      -                    [key_to_frag_number(State, KeyPat)];
      +                    [key_to_frag_number(State, KeyPat)];
                       true ->
      -                    lists:seq(1, N)
      +                    lists:seq(1, N)
                   end;
               _ ->
      -            lists:seq(1, N)
      +            lists:seq(1, N)
           end;
      /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap2.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (931))
      --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap2.html	2026-08-21 04:00:25.541334587 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap2.html	2026-08-21 04:00:25.540334580 +0000
      @@ -95,16 +95,16 @@
       mandatory procedures through examples:

      • Starting the Erlang session.
      • Specifying the Mnesia directory where the database is to be stored.
      • Initializing a new database schema with an attribute that specifies on which node, or nodes, that database is to operate.
      • Starting Mnesia.
      • Creating and populating the database tables.

      Starting Mnesia for the First Time

      This section provides a simplified demonstration of a Mnesia system startup. The dialogue from the Erlang shell is as follows:

      % erl -mnesia dir '"/tmp/funky"'
      -Erlang/OTP 27 [erts-15.1.2]
      +Erlang/OTP 27 [erts-15.1.2]
       
      -Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
      -1> mnesia:create_schema([node()]).
      +Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
      +1> mnesia:create_schema([node()]).
       ok
      -2> mnesia:start().
      +2> mnesia:start().
       ok
      -3> mnesia:create_table(funky, []).
      -{atomic,ok}
      -4> mnesia:info().
      +3> mnesia:create_table(funky, []).
      +{atomic,ok}
      +4> mnesia:info().
       ---> Processes holding locks <--- 
       ---> Processes waiting for locks <--- 
       ---> Participant transactions <--- 
      @@ -116,18 +116,18 @@
       ===> System info in version "4.23.2", debug level = none <===
       opt_disc. Directory "/tmp/funky" is used.
       use fallback at restart = false
      -running db nodes   = [nonode@nohost]
      -stopped db nodes   = []
      -master node tables = []
      -remote             = []
      -ram_copies         = [funky]
      -disc_copies        = [schema]
      -disc_only_copies   = []
      -[{nonode@nohost,disc_copies}] = [schema]
      -[{nonode@nohost,ram_copies}] = [funky]
      +running db nodes   = [nonode@nohost]
      +stopped db nodes   = []
      +master node tables = []
      +remote             = []
      +ram_copies         = [funky]
      +disc_copies        = [schema]
      +disc_only_copies   = []
      +[{nonode@nohost,disc_copies}] = [schema]
      +[{nonode@nohost,ram_copies}] = [funky]
       3 transactions committed, 0 aborted, 0 restarted, 2 logged to disc
       0 held locks, 0 in queue; 0 local transactions, 0 remote
      -0 transactions waits for other nodes: []
      +0 transactions waits for other nodes: []
       ok

      In this example, the following actions are performed:

      • Step 1: The Erlang system is started from the UNIX prompt with a flag -mnesia dir '"/tmp/funky"', which indicates in which directory to store the data.
      • Step 2: A new empty schema is initialized on the local node by evaluating @@ -169,28 +169,28 @@ Employee }|--|| Dept: At_dep Employee }|--|{ Project: in_proj

      The database model is as follows:

      • There are three entities: department, employee, and project.
      • There are three relationships between these entities:
        1. A department is managed by an employee, hence the manager relationship.
        2. An employee works at a department, hence the at_dep relationship.
        3. Each employee works on a number of projects, hence the in_proj relationship.

      Defining Structure and Content

      First the record definitions are entered into a text file named company.hrl. -This file defines the following structure for the example database:

      -record(employee, {emp_no,
      +This file defines the following structure for the example database:

      -record(employee, {emp_no,
                          name,
                          salary,
                          sex,
                          phone,
      -                   room_no}).
      +                   room_no}).
       
      --record(dept, {id,
      -               name}).
      +-record(dept, {id,
      +               name}).
       
      --record(project, {name,
      -                  number}).
      +-record(project, {name,
      +                  number}).
       
       
      --record(manager, {emp,
      -                  dept}).
      +-record(manager, {emp,
      +                  dept}).
       
      --record(at_dep, {emp,
      -                 dept_id}).
      +-record(at_dep, {emp,
      +                 dept_id}).
       
      --record(in_proj, {emp,
      -                  proj_name}).

      The structure defines six tables in the database. In Mnesia, the function +-record(in_proj, {emp, + proj_name}).

      The structure defines six tables in the database. In Mnesia, the function mnesia:create_table(Name, Opts) creates tables. Name is the table name.

      Note

      The current version of Mnesia does not require that the name of the table is the same as the record name, see @@ -201,28 +201,28 @@ preprocessor and evaluates to a list containing the names of the different fields for a record.

      Program

      The following shell interaction starts Mnesia and initializes the schema for the Company database:

      % erl -mnesia dir '"/ldisc/scratch/Mnesia.Company"'
      -Erlang/OTP 27 [erts-15.1.2]
      +Erlang/OTP 27 [erts-15.1.2]
       
      -Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
      -1> mnesia:create_schema([node()]).
      +Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
      +1> mnesia:create_schema([node()]).
       ok
      -2> mnesia:start().
      -ok

      The following program module creates and populates previously defined tables:

      -include_lib("stdlib/include/qlc.hrl").
      --include("company.hrl").
      -
      -init() ->
      -    mnesia:create_table(employee,
      -                        [{attributes, record_info(fields, employee)}]),
      -    mnesia:create_table(dept,
      -                        [{attributes, record_info(fields, dept)}]),
      -    mnesia:create_table(project,
      -                        [{attributes, record_info(fields, project)}]),
      -    mnesia:create_table(manager, [{type, bag},
      -                                  {attributes, record_info(fields, manager)}]),
      -    mnesia:create_table(at_dep,
      -                         [{attributes, record_info(fields, at_dep)}]),
      -    mnesia:create_table(in_proj, [{type, bag},
      -                                  {attributes, record_info(fields, in_proj)}]).

      Program Explained

      The following commands and functions are used to initiate the Company +2> mnesia:start(). +ok

      The following program module creates and populates previously defined tables:

      -include_lib("stdlib/include/qlc.hrl").
      +-include("company.hrl").
      +
      +init() ->
      +    mnesia:create_table(employee,
      +                        [{attributes, record_info(fields, employee)}]),
      +    mnesia:create_table(dept,
      +                        [{attributes, record_info(fields, dept)}]),
      +    mnesia:create_table(project,
      +                        [{attributes, record_info(fields, project)}]),
      +    mnesia:create_table(manager, [{type, bag},
      +                                  {attributes, record_info(fields, manager)}]),
      +    mnesia:create_table(at_dep,
      +                         [{attributes, record_info(fields, at_dep)}]),
      +    mnesia:create_table(in_proj, [{type, bag},
      +                                  {attributes, record_info(fields, in_proj)}]).

      Program Explained

      The following commands and functions are used to initiate the Company database:

      • % erl -mnesia dir '"/ldisc/scratch/Mnesia.Company"'. This is a UNIX command-line entry that starts the Erlang system. The flag -mnesia dir Dir specifies the location of the database directory. The system responds and @@ -230,9 +230,9 @@ the format mnesia:create_schema(DiscNodeList) and initiates a new schema. In this example, a non-distributed system using only one node is created. Schemas are fully explained in Define a Schema.
      • mnesia:start(). This function starts Mnesia and is fully -explained in Start Mnesia.

      Continuing the dialogue with the Erlang shell produces the following:

      3> company:init().
      -{atomic,ok}
      -4> mnesia:info().
      +explained in Start Mnesia.

      Continuing the dialogue with the Erlang shell produces the following:

      3> company:init().
      +{atomic,ok}
      +4> mnesia:info().
       ---> Processes holding locks <--- 
       ---> Processes waiting for locks <--- 
       ---> Participant transactions <--- 
      @@ -249,18 +249,18 @@
       ===> System info in version "4.23.2", debug level = none <===
       opt_disc. Directory "/ldisc/scratch/Mnesia.Company" is used.
       use fallback at restart = false
      -running db nodes   = [nonode@nohost]
      -stopped db nodes   = []
      -master node tables = []
      -remote             = []
      -ram_copies         = [at_dep,dept,employee,in_proj,manager,project]
      -disc_copies        = [schema]
      -disc_only_copies   = []
      -[{nonode@nohost,disc_copies}] = [schema]
      -[{nonode@nohost,ram_copies}] = [employee,dept,project,manager,at_dep,in_proj]
      +running db nodes   = [nonode@nohost]
      +stopped db nodes   = []
      +master node tables = []
      +remote             = []
      +ram_copies         = [at_dep,dept,employee,in_proj,manager,project]
      +disc_copies        = [schema]
      +disc_only_copies   = []
      +[{nonode@nohost,disc_copies}] = [schema]
      +[{nonode@nohost,ram_copies}] = [employee,dept,project,manager,at_dep,in_proj]
       8 transactions committed, 0 aborted, 0 restarted, 12 logged to disc
       0 held locks, 0 in queue; 0 local transactions, 0 remote
      -0 transactions waits for other nodes: []
      +0 transactions waits for other nodes: []
       ok

      A set of tables is created. The function mnesia:create_table(Name, Opts) creates the required database tables. The options available with Opts are explained in @@ -274,32 +274,32 @@ transactions have been committed, as six successful transactions were run when creating the tables.

      To write a function that inserts an employee record into the database, there must be an at_dep record and a set of in_proj records inserted. Examine the -following code used to complete this action:

      insert_emp(Emp, DeptId, ProjNames) ->
      +following code used to complete this action:

      insert_emp(Emp, DeptId, ProjNames) ->
           Ename = Emp#employee.name,
      -    Fun = fun() ->
      -                  mnesia:write(Emp),
      -                  AtDep = #at_dep{emp = Ename, dept_id = DeptId},
      -                  mnesia:write(AtDep),
      -                  mk_projs(Ename, ProjNames)
      +    Fun = fun() ->
      /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap3.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1223))
      --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap3.html	2026-08-21 04:00:25.564334736 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap3.html	2026-08-21 04:00:25.564334736 +0000
      @@ -127,18 +127,18 @@
       changes the format on all records in table Tab. It applies argument Fun to
       all records in the table. Fun must be a function that takes a record of the
       old type, and returns the record of the new type. The table key must not be
      -changed.

      Example:

      -record(old, {key, val}).
      --record(new, {key, val, extra}).
      +changed.

      Example:

      -record(old, {key, val}).
      +-record(new, {key, val, extra}).
       
       Transformer =
      -   fun(X) when record(X, old) ->
      -      #new{key = X#old.key,
      +   fun(X) when record(X, old) ->
      +      #new{key = X#old.key,
                  val = X#old.val,
      -           extra = 42}
      +           extra = 42}
          end,
      -{atomic, ok} = mnesia:transform_table(foo, Transformer,
      -                                      record_info(fields, new),
      -                                      new),

      Argument Fun can also be the atom ignore, which indicates that only the +{atomic, ok} = mnesia:transform_table(foo, Transformer, + record_info(fields, new), + new),

      Argument Fun can also be the atom ignore, which indicates that only the metadata about the table is updated. Use of ignore is not recommended (as it creates inconsistencies between the metadata and the actual data) but it is included as a possibility for the user do to an own (offline) transform.

    15. mnesia:change_table_copy_type(Tab, Node, ToType) @@ -172,29 +172,29 @@ when starting the Erlang shell or in the application script. Previously, the following example was used to create the directory for the Company database:

      % erl -mnesia dir '"/ldisc/scratch/Mnesia.Company"'
    16. If no command-line flag is entered, the Mnesia directory becomes the current working directory on the node where the Erlang shell is started.

    17. To start the Company database and get it running on the two specified nodes, -enter the following commands:

      1. On the node a@gin:
       gin % erl -sname a  -mnesia dir '"/ldisc/scratch/Mnesia.company"'
      1. On the node b@skeppet:
      skeppet % erl -sname b -mnesia dir '"/ldisc/scratch/Mnesia.company"'
      1. On one of the two nodes:
      (a@gin)1> mnesia:create_schema([a@gin, b@skeppet]).
      1. The function mnesia:start() is called on both nodes.
      2. To initialize the database, execute the following code on one of the two -nodes:
      dist_init() ->
      -    mnesia:create_table(employee,
      -                         [{ram_copies, [a@gin, b@skeppet]},
      -                          {attributes, record_info(fields,
      -                                                   employee)}]),
      -    mnesia:create_table(dept,
      -                         [{ram_copies, [a@gin, b@skeppet]},
      -                          {attributes, record_info(fields, dept)}]),
      -    mnesia:create_table(project,
      -                         [{ram_copies, [a@gin, b@skeppet]},
      -                          {attributes, record_info(fields, project)}]),
      -    mnesia:create_table(manager, [{type, bag},
      -                                  {ram_copies, [a@gin, b@skeppet]},
      -                                  {attributes, record_info(fields,
      -                                                           manager)}]),
      -    mnesia:create_table(at_dep,
      -                         [{ram_copies, [a@gin, b@skeppet]},
      -                          {attributes, record_info(fields, at_dep)}]),
      -    mnesia:create_table(in_proj,
      -                        [{type, bag},
      -                         {ram_copies, [a@gin, b@skeppet]},
      -                         {attributes, record_info(fields, in_proj)}]).

      As illustrated, the two directories reside on different nodes, because +enter the following commands:

      1. On the node a@gin:
       gin % erl -sname a  -mnesia dir '"/ldisc/scratch/Mnesia.company"'
      1. On the node b@skeppet:
      skeppet % erl -sname b -mnesia dir '"/ldisc/scratch/Mnesia.company"'
      1. On one of the two nodes:
      (a@gin)1> mnesia:create_schema([a@gin, b@skeppet]).
      1. The function mnesia:start() is called on both nodes.
      2. To initialize the database, execute the following code on one of the two +nodes:
      dist_init() ->
      +    mnesia:create_table(employee,
      +                         [{ram_copies, [a@gin, b@skeppet]},
      +                          {attributes, record_info(fields,
      +                                                   employee)}]),
      +    mnesia:create_table(dept,
      +                         [{ram_copies, [a@gin, b@skeppet]},
      +                          {attributes, record_info(fields, dept)}]),
      +    mnesia:create_table(project,
      +                         [{ram_copies, [a@gin, b@skeppet]},
      +                          {attributes, record_info(fields, project)}]),
      +    mnesia:create_table(manager, [{type, bag},
      +                                  {ram_copies, [a@gin, b@skeppet]},
      +                                  {attributes, record_info(fields,
      +                                                           manager)}]),
      +    mnesia:create_table(at_dep,
      +                         [{ram_copies, [a@gin, b@skeppet]},
      +                          {attributes, record_info(fields, at_dep)}]),
      +    mnesia:create_table(in_proj,
      +                        [{type, bag},
      +                         {ram_copies, [a@gin, b@skeppet]},
      +                         {attributes, record_info(fields, in_proj)}]).

      As illustrated, the two directories reside on different nodes, because /ldisc/scratch (the "local" disc) exists on the two different nodes.

      By executing these commands, two Erlang nodes are configured to run the Company database, and therefore, initialize the database. This is required only once when setting up. The next time the system is started, @@ -205,7 +205,7 @@ Code that manipulate Mnesia data behaves identically regardless of where the data resides.

      The function mnesia:stop() stops Mnesia on the node where the function is executed. The functions mnesia:start/0 and mnesia:stop/0 -work on the "local" Mnesia system. No functions start or stop a set of nodes.

      Startup Procedure

      Start Mnesia by calling the following function:

      mnesia:start().

      This function initiates the DBMS locally.

      The choice of configuration alters the location and load order of the tables. +work on the "local" Mnesia system. No functions start or stop a set of nodes.

      Startup Procedure

      Start Mnesia by calling the following function:

      mnesia:start().

      This function initiates the DBMS locally.

      The choice of configuration alters the location and load order of the tables. The alternatives are as follows:

      1. Tables that are only stored locally are initialized from the local Mnesia directory.
      2. Replicated tables that reside locally as well as somewhere else are either initiated from disc or by copying the entire table from the other node, @@ -228,9 +228,9 @@ from disc at a faster rate. The function forces tables to be loaded from disc regardless of the network situation.

        Thus, it can be assumed that if an application wants to use tables a and b, the application must perform some action similar to following before it can use -the tables:

        case mnesia:wait_for_tables([a, b], 20000) of
        -  {timeout, RemainingTabs} ->
        -    panic(RemainingTabs);
        +the tables:

        case mnesia:wait_for_tables([a, b], 20000) of
        +  {timeout, RemainingTabs} ->
        +    panic(RemainingTabs);
           ok ->
             synced
         end.

        Warning

        When tables are forcefully loaded from the local disc, all operations that @@ -250,13 +250,13 @@ key, whereas a table of type bag can have an arbitrary number of records per key. The key for each record is always the first attribute of the record.

        The following example illustrates the difference between type set and -bag:

         f() ->
        -    F = fun() ->
        -          mnesia:write({foo, 1, 2}),
        -          mnesia:write({foo, 1, 3}),
        -          mnesia:read({foo, 1})
        +bag:

         f() ->
        +    F = fun() ->
        +          mnesia:write({foo, 1, 2}),
        +          mnesia:write({foo, 1, 3}),
        +          mnesia:read({foo, 1})
                 end,
        -    mnesia:transaction(F).

        This transaction returns the list [{foo,1,3}] if table foo is of type + mnesia:transaction(F).

        This transaction returns the list [{foo,1,3}] if table foo is of type set. However, the list [{foo,1,2}, {foo,1,3}] is returned if the table is of type bag.

        Mnesia tables can never contain duplicates of the same record in the same table. Duplicate records have attributes with the same contents and key.

      3. {disc_copies, NodeList}, where NodeList is a list of the nodes where @@ -300,11 +300,11 @@ table. All records stored in the table must have this name as their first element. record_name defaults to the name of the table. For more information, see -Record Names versus Table Names.

      4. As an example, consider the following record definition:

        -record(funky, {x, y}).

        The following call would create a table that is replicated on two nodes, has an -extra index on attribute y, and is of type bag.

        mnesia:create_table(funky, [{disc_copies, [N1, N2]}, {index, [y]},
        -                            {type, bag}, {attributes, record_info(fields, funky)}]).

        Whereas a call to the following default code values would return a table with a +Record Names versus Table Names.

        As an example, consider the following record definition:

        -record(funky, {x, y}).

        The following call would create a table that is replicated on two nodes, has an +extra index on attribute y, and is of type bag.

        mnesia:create_table(funky, [{disc_copies, [N1, N2]}, {index, [y]},
        +                            {type, bag}, {attributes, record_info(fields, funky)}]).

        Whereas a call to the following default code values would return a table with a RAM copy on the local node, no extra indexes, and the attributes defaulted to -the list [key,val].

        mnesia:create_table(stuff, [])
        +the list [key,val].

        mnesia:create_table(stuff, [])
        /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap4.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1020)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap4.html 2026-08-21 04:00:25.591334912 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap4.html 2026-08-21 04:00:25.592334919 +0000 @@ -103,14 +103,14 @@ and delete Mnesia records. The Fun is evaluated as a transaction that either commits or terminates. If a transaction succeeds in executing the Fun, it replicates the action on all nodes involved, or terminates if an error occurs.

        The following example shows a transaction that raises the salary of certain -employee numbers:

        raise(Eno, Raise) ->
        -    F = fun() ->
        -                [E] = mnesia:read(employee, Eno, write),
        +employee numbers:

        raise(Eno, Raise) ->
        +    F = fun() ->
        +                [E] = mnesia:read(employee, Eno, write),
                         Salary = E#employee.salary + Raise,
        -                New = E#employee{salary = Salary},
        -                mnesia:write(New)
        +                New = E#employee{salary = Salary},
        +                mnesia:write(New)
                 end,
        -    mnesia:transaction(F).

        The function raise/2 contains a Fun made up of four code lines. This Fun is + mnesia:transaction(F).

        The function raise/2 contains a Fun made up of four code lines. This Fun is called by the statement mnesia:transaction(F) and returns a value.

        The Mnesia transaction system facilitates the construction of reliable, distributed systems by providing the following important properties:

        • The transaction handler ensures that a Fun, which is placed inside a transaction, does not interfere with operations embedded in other transactions @@ -174,15 +174,15 @@ The Fun in the transaction is evaluated once more.

          It is therefore important that the code inside the Fun given to mnesia:transaction/1 is pure. Some strange results can occur if, for example, messages are sent by the transaction Fun. The following example illustrates this -situation:

          bad_raise(Eno, Raise) ->
          -    F = fun() ->
          -                [E] = mnesia:read({employee, Eno}),
          +situation:

          bad_raise(Eno, Raise) ->
          +    F = fun() ->
          +                [E] = mnesia:read({employee, Eno}),
                           Salary = E#employee.salary + Raise,
          -                New = E#employee{salary = Salary},
          -                io:format("Trying to write ... ~n", []),
          -                mnesia:write(New)
          +                New = E#employee{salary = Salary},
          +                io:format("Trying to write ... ~n", []),
          +                mnesia:write(New)
                   end,
          -    mnesia:transaction(F).

          This transaction can write the text "Trying to write ... " 1000 times to the + mnesia:transaction(F).

          This transaction can write the text "Trying to write ... " 1000 times to the terminal. However, Mnesia guarantees that each transaction will eventually run. As a result, Mnesia is not only deadlock free, but also livelock free.

          The Mnesia programmer cannot prioritize one particular transaction to execute before other transactions that are waiting to execute. As a result, the Mnesia @@ -223,13 +223,13 @@ fails. Such applications can benefit from using sticky locks instead of the normal locking scheme.

          A sticky lock is a lock that stays in place at a node, after the transaction that first acquired the lock has terminated. To illustrate this, assume that the -following transaction is executed:

          F = fun() ->
          -      mnesia:write(#foo{a = kalle})
          +following transaction is executed:

          F = fun() ->
          +      mnesia:write(#foo{a = kalle})
               end,
          -mnesia:transaction(F).

          The foo table is replicated on the two nodes N1 and N2.

          Normal locking requires the following:

          • One network RPC (two messages) to acquire the write lock
          • Three network messages to execute the two-phase commit protocol

          If sticky locks are used, the code must first be changed as follows:

          F = fun() ->
          -      mnesia:s_write(#foo{a = kalle})
          +mnesia:transaction(F).

          The foo table is replicated on the two nodes N1 and N2.

          Normal locking requires the following:

          • One network RPC (two messages) to acquire the write lock
          • Three network messages to execute the two-phase commit protocol

          If sticky locks are used, the code must first be changed as follows:

          F = fun() ->
          +      mnesia:s_write(#foo{a = kalle})
               end,
          -mnesia:transaction(F).

          This code uses the function s_write/1 instead of the +mnesia:transaction(F).

          This code uses the function s_write/1 instead of the function write/1 The function s_write/1 sets a sticky lock instead of a normal lock. If the table is not replicated, sticky locks have no special effect. If the table is replicated, and a sticky lock is set on node @@ -249,8 +249,8 @@ following two functions are used to set explicit table locks for read and write operations:

          Alternative syntax for acquisition of table locks is as follows:

          mnesia:lock({table, Tab}, read)
          -mnesia:lock({table, Tab}, write)

          The matching operations in Mnesia can either lock the entire table or only a +on table Tab.

        Alternative syntax for acquisition of table locks is as follows:

        mnesia:lock({table, Tab}, read)
        +mnesia:lock({table, Tab}, write)

        The matching operations in Mnesia can either lock the entire table or only a single record (when the key is bound in the pattern).

        Global Locks

        Write locks are normally acquired on all nodes where a replica of the table resides (and is active). Read locks are acquired on one node (the local one if a local replica exists).

        The function mnesia:lock/2 is intended to support table locks (as mentioned @@ -323,78 +323,78 @@ necessarily have to be the same as the table name, although this is the case in most of the examples in this User's Guide. If a table is created without property record_name, the following code ensures that all records in the -tables have the same name as the table:

        mnesia:create_table(subscriber, [])

        However, if the table is created with an explicit record name as argument, as +tables have the same name as the table:

        mnesia:create_table(subscriber, [])

        However, if the table is created with an explicit record name as argument, as shown in the following example, subscriber records can be stored in both of the -tables regardless of the table names:

        TabDef = [{record_name, subscriber}],
        -mnesia:create_table(my_subscriber, TabDef),
        -mnesia:create_table(your_subscriber, TabDef).

        To access such tables, simplified access functions (as described earlier) cannot +tables regardless of the table names:

        TabDef = [{record_name, subscriber}],
        +mnesia:create_table(my_subscriber, TabDef),
        +mnesia:create_table(your_subscriber, TabDef).

        To access such tables, simplified access functions (as described earlier) cannot be used. For example, writing a subscriber record into a table requires the function mnesia:write/3 instead of the simplified functions mnesia:write/1 -and mnesia:s_write/1:

        mnesia:write(subscriber, #subscriber{}, write)
        -mnesia:write(my_subscriber, #subscriber{}, sticky_write)
        -mnesia:write(your_subscriber, #subscriber{}, write)

        The following simple code illustrates the relationship between the simplified +and mnesia:s_write/1:

        mnesia:write(subscriber, #subscriber{}, write)
        +mnesia:write(my_subscriber, #subscriber{}, sticky_write)
        +mnesia:write(your_subscriber, #subscriber{}, write)

        The following simple code illustrates the relationship between the simplified access functions used in most of the examples and their more flexible -counterparts:

        mnesia:dirty_write(Record) ->
        -  Tab = element(1, Record),
        -  mnesia:dirty_write(Tab, Record).
        +counterparts:

        mnesia:dirty_write(Record) ->
        +  Tab = element(1, Record),
        +  mnesia:dirty_write(Tab, Record).
         
        -mnesia:dirty_delete({Tab, Key}) ->
        -  mnesia:dirty_delete(Tab, Key).
        +mnesia:dirty_delete({Tab, Key}) ->
        +  mnesia:dirty_delete(Tab, Key).
         
        -mnesia:dirty_delete_object(Record) ->
        -  Tab = element(1, Record),
        -  mnesia:dirty_delete_object(Tab, Record)
        +mnesia:dirty_delete_object(Record) ->
        +  Tab = element(1, Record),
        +  mnesia:dirty_delete_object(Tab, Record)
         
        -mnesia:dirty_update_counter({Tab, Key}, Incr) ->
        -  mnesia:dirty_update_counter(Tab, Key, Incr).
        +mnesia:dirty_update_counter({Tab, Key}, Incr) ->
        +  mnesia:dirty_update_counter(Tab, Key, Incr).
         
        -mnesia:dirty_read({Tab, Key}) ->
        -  Tab = element(1, Record),
        -  mnesia:dirty_read(Tab, Key).
        +mnesia:dirty_read({Tab, Key}) ->
        +  Tab = element(1, Record),
        +  mnesia:dirty_read(Tab, Key).
         
        -mnesia:dirty_match_object(Pattern) ->
        -  Tab = element(1, Pattern),
        -  mnesia:dirty_match_object(Tab, Pattern).
        +mnesia:dirty_match_object(Pattern) ->
        +  Tab = element(1, Pattern),
        +  mnesia:dirty_match_object(Tab, Pattern).
         
        -mnesia:dirty_index_match_object(Pattern, Attr)
        -  Tab = element(1, Pattern),
        -  mnesia:dirty_index_match_object(Tab, Pattern, Attr).
        +mnesia:dirty_index_match_object(Pattern, Attr)
        +  Tab = element(1, Pattern),
        +  mnesia:dirty_index_match_object(Tab, Pattern, Attr).
         
        -mnesia:write(Record) ->
        -  Tab = element(1, Record),
        -  mnesia:write(Tab, Record, write).
        +mnesia:write(Record) ->
        +  Tab = element(1, Record),
        +  mnesia:write(Tab, Record, write).
         
        -mnesia:s_write(Record) ->
        -  Tab = element(1, Record),
        -  mnesia:write(Tab, Record, sticky_write).
        +mnesia:s_write(Record) ->
        +  Tab = element(1, Record),
        +  mnesia:write(Tab, Record, sticky_write).
         
        -mnesia:delete({Tab, Key}) ->
        -  mnesia:delete(Tab, Key, write).
        +mnesia:delete({Tab, Key}) ->
        +  mnesia:delete(Tab, Key, write).
         
        -mnesia:s_delete({Tab, Key}) ->
        -  mnesia:delete(Tab, Key, sticky_write).
        +mnesia:s_delete({Tab, Key}) ->
        +  mnesia:delete(Tab, Key, sticky_write).
         
        -mnesia:delete_object(Record) ->
        -  Tab = element(1, Record),
        -  mnesia:delete_object(Tab, Record, write).
        +mnesia:delete_object(Record) ->
        +  Tab = element(1, Record),
        +  mnesia:delete_object(Tab, Record, write).
         
        -mnesia:s_delete_object(Record) ->
        -  Tab = element(1, Record),
        -  mnesia:delete_object(Tab, Record, sticky_write).
        +mnesia:s_delete_object(Record) ->
        +  Tab = element(1, Record),
        +  mnesia:delete_object(Tab, Record, sticky_write).
         
        -mnesia:read({Tab, Key}) ->
        -  mnesia:read(Tab, Key, read).
        +mnesia:read({Tab, Key}) ->
        +  mnesia:read(Tab, Key, read).
         
        -mnesia:wread({Tab, Key}) ->
        -  mnesia:read(Tab, Key, write).
        +mnesia:wread({Tab, Key}) ->
        +  mnesia:read(Tab, Key, write).
         
        -mnesia:match_object(Pattern) ->
        -  Tab = element(1, Pattern),
        -  mnesia:match_object(Tab, Pattern, read).
        +mnesia:match_object(Pattern) ->
        +  Tab = element(1, Pattern),
        +  mnesia:match_object(Tab, Pattern, read).
         
        -mnesia:index_match_object(Pattern, Attr) ->
        -  Tab = element(1, Pattern),
        /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap5.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1275))
        --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap5.html	2026-08-21 04:00:25.625335133 +0000
        +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap5.html	2026-08-21 04:00:25.625335133 +0000
        @@ -119,9 +119,9 @@
         whether the data resides on the local node or on a remote node.

        Notice that the program runs slower if the data is located on a remote node.

      5. The database can be reconfigured, and tables can be moved between nodes. These operations do not affect the user programs.

      6. It has previously been shown that each table has a number of system attributes, such as index and type.

        Table attributes are specified when the table is created. For example, the -following function creates a table with two RAM replicas:

        mnesia:create_table(foo,
        -                    [{ram_copies, [N1, N2]},
        -                     {attributes, record_info(fields, foo)}]).

        Tables can also have the following properties, where each attribute has a list +following function creates a table with two RAM replicas:

        mnesia:create_table(foo,
        +                    [{ram_copies, [N1, N2]},
        +                     {attributes, record_info(fields, foo)}]).

        Tables can also have the following properties, where each attribute has a list of Erlang nodes as its value:

        • ram_copies. The value of the node list is a list of Erlang nodes, and a RAM replica of the table resides on each node in the list.

          Notice that no disc operations are performed when a program executes write operations to these replicas. However, if permanent RAM replicas are required, @@ -162,52 +162,52 @@ searched for matching records.

          Notice that in ordered_set tables, the records are ordered per fragment, and the order is undefined in results returned by select and match_object, as well as first, next, prev and last.

          The following code illustrates how a Mnesia table is converted to be a -fragmented table and how more fragments are added later:

          Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
          -(a@sam)1> mnesia:start().
          +fragmented table and how more fragments are added later:

          Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
          +(a@sam)1> mnesia:start().
           ok
          -(a@sam)2> mnesia:system_info(running_db_nodes).
          -[b@sam,c@sam,a@sam]
          +(a@sam)2> mnesia:system_info(running_db_nodes).
          +[b@sam,c@sam,a@sam]
           (a@sam)3> Tab = dictionary.
           dictionary
          -(a@sam)4> mnesia:create_table(Tab, [{ram_copies, [a@sam, b@sam]}]).
          -{atomic,ok}
          -(a@sam)5> Write = fun(Keys) -> [mnesia:write({Tab,K,-K}) || K <- Keys], ok end.
          +(a@sam)4> mnesia:create_table(Tab, [{ram_copies, [a@sam, b@sam]}]).
          +{atomic,ok}
          +(a@sam)5> Write = fun(Keys) -> [mnesia:write({Tab,K,-K}) || K <- Keys], ok end.
           #Fun<erl_eval>
          -(a@sam)6> mnesia:activity(sync_dirty, Write, [lists:seq(1, 256)], mnesia_frag).
          +(a@sam)6> mnesia:activity(sync_dirty, Write, [lists:seq(1, 256)], mnesia_frag).
           ok
          -(a@sam)7> mnesia:change_table_frag(Tab, {activate, []}).
          -{atomic,ok}
          -(a@sam)8> mnesia:table_info(Tab, frag_properties).
          -[{base_table,dictionary},
          - {foreign_key,undefined},
          - {hash_module,mnesia_frag_hash},
          - {hash_state,{hash_state,1,1,0,phash2}},
          - {n_fragments,1},
          - {node_pool,[a@sam,b@sam,c@sam]}]
          -(a@sam)9> Info = fun(Item) -> mnesia:table_info(Tab, Item) end.
          +(a@sam)7> mnesia:change_table_frag(Tab, {activate, []}).
          +{atomic,ok}
          +(a@sam)8> mnesia:table_info(Tab, frag_properties).
          +[{base_table,dictionary},
          + {foreign_key,undefined},
          + {hash_module,mnesia_frag_hash},
          + {hash_state,{hash_state,1,1,0,phash2}},
          + {n_fragments,1},
          + {node_pool,[a@sam,b@sam,c@sam]}]
          +(a@sam)9> Info = fun(Item) -> mnesia:table_info(Tab, Item) end.
           #Fun<erl_eval>
          -(a@sam)10> Dist = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
          -[{c@sam,0},{a@sam,1},{b@sam,1}]
          -(a@sam)11> mnesia:change_table_frag(Tab, {add_frag, Dist}).
          -{atomic,ok}
          -(a@sam)12> Dist2 = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
          -[{b@sam,1},{c@sam,1},{a@sam,2}]
          -(a@sam)13> mnesia:change_table_frag(Tab, {add_frag, Dist2}).
          -{atomic,ok}
          -(a@sam)14> Dist3 = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
          -[{a@sam,2},{b@sam,2},{c@sam,2}]
          -(a@sam)15> mnesia:change_table_frag(Tab, {add_frag, Dist3}).
          -{atomic,ok}
          -(a@sam)16> Read = fun(Key) -> mnesia:read({Tab, Key}) end.
          +(a@sam)10> Dist = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
          +[{c@sam,0},{a@sam,1},{b@sam,1}]
          +(a@sam)11> mnesia:change_table_frag(Tab, {add_frag, Dist}).
          +{atomic,ok}
          +(a@sam)12> Dist2 = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
          +[{b@sam,1},{c@sam,1},{a@sam,2}]
          +(a@sam)13> mnesia:change_table_frag(Tab, {add_frag, Dist2}).
          +{atomic,ok}
          +(a@sam)14> Dist3 = mnesia:activity(sync_dirty, Info, [frag_dist], mnesia_frag).
          +[{a@sam,2},{b@sam,2},{c@sam,2}]
          +(a@sam)15> mnesia:change_table_frag(Tab, {add_frag, Dist3}).
          +{atomic,ok}
          +(a@sam)16> Read = fun(Key) -> mnesia:read({Tab, Key}) end.
           #Fun<erl_eval>
          -(a@sam)17> mnesia:activity(transaction, Read, [12], mnesia_frag).
          -[{dictionary,12,-12}]
          -(a@sam)18> mnesia:activity(sync_dirty, Info, [frag_size], mnesia_frag).
          -[{dictionary,57},
          - {dictionary_frag2,63},
          - {dictionary_frag3,62},
          - {dictionary_frag4,74}]
          -(a@sam)19>

          Fragmentation Properties

          The table property frag_properties can be read with the function +(a@sam)17> mnesia:activity(transaction, Read, [12], mnesia_frag). +[{dictionary,12,-12}] +(a@sam)18> mnesia:activity(sync_dirty, Info, [frag_size], mnesia_frag). +[{dictionary,57}, + {dictionary_frag2,63}, + {dictionary_frag3,62}, + {dictionary_frag4,74}] +(a@sam)19>

          Fragmentation Properties

          The table property frag_properties can be read with the function mnesia:table_info(Tab, frag_properties). The fragmentation properties are a list of tagged tuples with arity 2. By default the list is empty, but when it is non-empty it triggers Mnesia to regard the @@ -243,64 +243,64 @@ This property can explicitly be set at table creation. Default is mnesia_frag_hash.

        • {hash_state, Term} - Enables a table-specific parameterization of a generic hash module. This property can explicitly be set at table creation. -Default is undefined.

          Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
          -(a@sam)1> mnesia:start().
          +Default is undefined.

          Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
          +(a@sam)1> mnesia:start().
           ok
          -(a@sam)2> PrimProps = [{n_fragments, 7}, {node_pool, [node()]}].
          -[{n_fragments,7},{node_pool,[a@sam]}]
          -(a@sam)3> mnesia:create_table(prim_dict,
          -                              [{frag_properties, PrimProps},
          -                               {attributes, [prim_key, prim_val]}]).
          -{atomic,ok}
          -(a@sam)4> SecProps = [{foreign_key, {prim_dict, sec_val}}].
          -[{foreign_key,{prim_dict,sec_val}}]
          -(a@sam)5> mnesia:create_table(sec_dict,
          -                              [{frag_properties, SecProps},
          -                               {attributes, [sec_key, sec_val]}]).
          -{atomic,ok}
          -(a@sam)6> Write = fun(Rec) -> mnesia:write(Rec) end.
          +(a@sam)2> PrimProps = [{n_fragments, 7}, {node_pool, [node()]}].
          +[{n_fragments,7},{node_pool,[a@sam]}]
          +(a@sam)3> mnesia:create_table(prim_dict,
          +                              [{frag_properties, PrimProps},
          +                               {attributes, [prim_key, prim_val]}]).
          +{atomic,ok}
          +(a@sam)4> SecProps = [{foreign_key, {prim_dict, sec_val}}].
          +[{foreign_key,{prim_dict,sec_val}}]
          +(a@sam)5> mnesia:create_table(sec_dict,
          +                              [{frag_properties, SecProps},
          +                               {attributes, [sec_key, sec_val]}]).
          +{atomic,ok}
          +(a@sam)6> Write = fun(Rec) -> mnesia:write(Rec) end.
           #href_anchor"n">Fun<erl_eval>
           (a@sam)7> PrimKey = 11.
           11
           (a@sam)8> SecKey = 42.
           42
          -(a@sam)9> mnesia:activity(sync_dirty, Write,
          -                          [{prim_dict, PrimKey, -11}], mnesia_frag).
          +(a@sam)9> mnesia:activity(sync_dirty, Write,
          +                          [{prim_dict, PrimKey, -11}], mnesia_frag).
           ok
          -(a@sam)10> mnesia:activity(sync_dirty, Write,
          -                           [{sec_dict, SecKey, PrimKey}], mnesia_frag).
          +(a@sam)10> mnesia:activity(sync_dirty, Write,
          +                           [{sec_dict, SecKey, PrimKey}], mnesia_frag).
           ok
          -(a@sam)11> mnesia:change_table_frag(prim_dict, {add_frag, [node()]}).
          -{atomic,ok}
          -(a@sam)12> SecRead = fun(PrimKey, SecKey) ->
          -               mnesia:read({sec_dict, PrimKey}, SecKey, read) end.
          +(a@sam)11> mnesia:change_table_frag(prim_dict, {add_frag, [node()]}).
          +{atomic,ok}
          +(a@sam)12> SecRead = fun(PrimKey, SecKey) ->
          +               mnesia:read({sec_dict, PrimKey}, SecKey, read) end.
           #Fun<erl_eval>
          -(a@sam)13> mnesia:activity(transaction, SecRead,
          -                           [PrimKey, SecKey], mnesia_frag).
          -[{sec_dict,42,11}]
          -(a@sam)14> Info = fun(Tab, Item) -> mnesia:table_info(Tab, Item) end.
          +(a@sam)13> mnesia:activity(transaction, SecRead,
          +                           [PrimKey, SecKey], mnesia_frag).
          +[{sec_dict,42,11}]
          +(a@sam)14> Info = fun(Tab, Item) -> mnesia:table_info(Tab, Item) end.
           #Fun<erl_eval>
          -(a@sam)15> mnesia:activity(sync_dirty, Info,
          -                           [prim_dict, frag_size], mnesia_frag).
          -[{prim_dict,0},
          - {prim_dict_frag2,0},
          - {prim_dict_frag3,1},
          - {prim_dict_frag4,0},
          - {prim_dict_frag5,0},
          - {prim_dict_frag6,0},
          - {prim_dict_frag7,0},
          - {prim_dict_frag8,0}]
          -(a@sam)16> mnesia:activity(sync_dirty, Info,
          -                           [sec_dict, frag_size], mnesia_frag).
          -[{sec_dict,0},
          - {sec_dict_frag2,0},
          - {sec_dict_frag3,1},
          - {sec_dict_frag4,0},
          - {sec_dict_frag5,0},
          - {sec_dict_frag6,0},
          - {sec_dict_frag7,0},
          - {sec_dict_frag8,0}]
          -(a@sam)17>

        Management of Fragmented Tables

        The function mnesia:change_table_frag(Tab, Change) is intended to be used for +(a@sam)15> mnesia:activity(sync_dirty, Info, + [prim_dict, frag_size], mnesia_frag). +[{prim_dict,0}, + {prim_dict_frag2,0}, /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap7.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1110)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap7.html 2026-08-21 04:00:25.652335309 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_chap7.html 2026-08-21 04:00:25.653335316 +0000 @@ -161,26 +161,26 @@ for starting Mnesia:

        • An Erlang session must be started and a Mnesia directory must be specified for the database.
        • A database schema must be initiated, using the function mnesia:create_schema/1.

        The following example shows how these tasks are performed:

        Step 1: Start an Erlang session and specify a Mnesia directory for the -database:

        % erl -sname klacke -mnesia dir '"/ldisc/scratch/klacke"'
        Erlang/OTP 27 [erts-15.1.2]
        +database:

        % erl -sname klacke -mnesia dir '"/ldisc/scratch/klacke"'
        Erlang/OTP 27 [erts-15.1.2]
         
        -Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
        -(klacke@gin)1> mnesia:create_schema([node()]).
        +Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
        +(klacke@gin)1> mnesia:create_schema([node()]).
         ok
        -(klacke@gin)2>
        +(klacke@gin)2>
         Ctrl+Z
        -[1]+  Stopped                 erl

        Step 2: You can inspect the Mnesia directory to see what files have been +[1]+ Stopped erl

        Step 2: You can inspect the Mnesia directory to see what files have been created:

        % ls -l /ldisc/scratch/klacke
         -rw-rw-r--   1 klacke   staff       247 Aug 12 15:06 FALLBACK.BUP

        The response shows that the file FALLBACK.BUP has been created. This is called a backup file, and it contains an initial schema. If more than one node in the function mnesia:create_schema/1 had been specified, identical backup files -would have been created on all nodes.

        Step 3: Start Mnesia:

        (klacke@gin)3> mnesia:start().
        +would have been created on all nodes.

        Step 3: Start Mnesia:

        (klacke@gin)3> mnesia:start().
         ok

        Step 4: You can see the following listing in the Mnesia directory:

        -rw-rw-r--   1 klacke   staff         86 May 26 19:03 LATEST.LOG
         -rw-rw-r--   1 klacke   staff      34507 May 26 19:03 schema.DAT

        The schema in the backup file FALLBACK.BUP has been used to generate the file schema.DAT. Since there are no other disc resident tables than the schema, no other data files were created. The file FALLBACK.BUP was removed after the successful "restoration". You also see some files that are for internal use by -Mnesia.

        Step 5: Create a table:

        (klacke@gin)4> mnesia:create_table(foo,[{disc_copies, [node()]}]).
        -{atomic,ok}

        Step 6: You can see the following listing in the Mnesia directory:

        % ls -l /ldisc/scratch/klacke
        +Mnesia.

        Step 5: Create a table:

        (klacke@gin)4> mnesia:create_table(foo,[{disc_copies, [node()]}]).
        +{atomic,ok}

        Step 6: You can see the following listing in the Mnesia directory:

        % ls -l /ldisc/scratch/klacke
         -rw-rw-r-- 1 klacke staff    86 May 26 19:07 LATEST.LOG
         -rw-rw-r-- 1 klacke staff    94 May 26 19:07 foo.DCD
         -rw-rw-r-- 1 klacke staff  6679 May 26 19:07 schema.DAT

        The file foo.DCD has been created. This file will eventually store all data @@ -212,11 +212,11 @@ the Mnesia data files. For example, dets contains the function dets:traverse/2, which can be used to view the contents of a Mnesia DAT file. However, this can only be done when Mnesia is not running. So, to view -the schema file, do as follows;

        {ok, N} = dets:open_file(schema, [{file, "./schema.DAT"},{repair,false},
        -{keypos, 2}]),
        -F = fun(X) -> io:format("~p~n", [X]), continue end,
        -dets:traverse(N, F),
        -dets:close(N).

        Warning

        The DAT files must always be opened with option {repair, false}. This +the schema file, do as follows;

        {ok, N} = dets:open_file(schema, [{file, "./schema.DAT"},{repair,false},
        +{keypos, 2}]),
        +F = fun(X) -> io:format("~p~n", [X]), continue end,
        +dets:traverse(N, F),
        +dets:close(N).

        Warning

        The DAT files must always be opened with option {repair, false}. This ensures that these files are not automatically repaired. Without this option, the database can become inconsistent, because Mnesia can believe that the files were properly closed. For information about configuration parameter @@ -420,38 +420,38 @@ located first in the backup.

        The schema itself is a table and is possibly included in the backup. Each node where the schema table resides is regarded as a db_node.

        The following example shows how mnesia:traverse_backup can be used to rename a -db_node in a backup file:

        change_node_name(Mod, From, To, Source, Target) ->
        +db_node in a backup file:

        change_node_name(Mod, From, To, Source, Target) ->
             Switch =
        -        fun(Node) when Node == From -> To;
        -           (Node) when Node == To -> throw({error, already_exists});
        -           (Node) -> Node
        +        fun(Node) when Node == From -> To;
        +           (Node) when Node == To -> throw({error, already_exists});
        +           (Node) -> Node
                 end,
             Convert =
        -        fun({schema, version, Version}, Acc) ->
        -                {[{schema, version, Version}], Acc};
        -           ({schema, cookie, Cookie}, Acc) ->
        -                {[{schema, cookie, Cookie}], Acc};
        -           ({schema, Tab, CreateList}, Acc) ->
        -                Keys = [ram_copies, disc_copies, disc_only_copies],
        +        fun({schema, version, Version}, Acc) ->
        +                {[{schema, version, Version}], Acc};
        +           ({schema, cookie, Cookie}, Acc) ->
        +                {[{schema, cookie, Cookie}], Acc};
        +           ({schema, Tab, CreateList}, Acc) ->
        +                Keys = [ram_copies, disc_copies, disc_only_copies],
                         OptSwitch =
        -                    fun({Key, Val}) ->
        -                            case lists:member(Key, Keys) of
        -                                true -> {Key, lists:map(Switch, Val)};
        -                                false-> {Key, Val}
        +                    fun({Key, Val}) ->
        +                            case lists:member(Key, Keys) of
        +                                true -> {Key, lists:map(Switch, Val)};
        +                                false-> {Key, Val}
                                     end
                             end,
        -                {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc};
        -           (Other, Acc) ->
        -                {[Other], Acc}
        +                {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc};
        +           (Other, Acc) ->
        +                {[Other], Acc}
                 end,
        -    mnesia:traverse_backup(Source, Mod, Target, Mod, Convert, switched).
        +    mnesia:traverse_backup(Source, Mod, Target, Mod, Convert, switched).
         
        -view(Source, Mod) ->
        -    View = fun(Item, Acc) ->
        -                   io:format("~p.~n",[Item]),
        -                   {[Item], Acc + 1}
        +view(Source, Mod) ->
        +    View = fun(Item, Acc) ->
        +                   io:format("~p.~n",[Item]),
        +                   {[Item], Acc + 1}
                    end,
        -    mnesia:traverse_backup(Source, Mod, dummy, read_only, View, 0).

        Restore

        Tables can be restored online from a backup without restarting Mnesia. A + mnesia:traverse_backup(Source, Mod, dummy, read_only, View, 0).

        Restore

        Tables can be restored online from a backup without restarting Mnesia. A restore is performed with the function mnesia:restore(Opaque, Args), where Args can contain the following tuples:

        • {module, Mod}. The backup module Mod is used to access the backup media. If /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_registry.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (966)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_registry.html 2026-08-21 04:00:25.672335439 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/mnesia_registry.html 2026-08-21 04:00:25.673335446 +0000 @@ -217,8 +217,8 @@

          Warning

          This function is deprecated. Do not use it.

          A wrapper function for mnesia:create_table/2, which creates a table (if there is no existing table) with an appropriate set of attributes. The attributes and TabDef are forwarded to mnesia:create_table/2. For example, if the table -is to reside as disc_only_copies on all nodes, a call looks as follows:

                    TabDef = [{{disc_only_copies, node()|nodes()]}],
          -          mnesia_registry:create_table(my_reg, TabDef)
          +is to reside as disc_only_copies on all nodes, a call looks as follows:

                    TabDef = [{{disc_only_copies, node()|nodes()]}],
          +          mnesia_registry:create_table(my_reg, TabDef)
        /usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (8813)) --- old//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/notes.html 2026-08-21 04:00:25.700335622 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/mnesia-4.25.3.1/doc/html/notes.html 2026-08-21 04:00:25.700335622 +0000 @@ -94,9 +94,9 @@ as all enhancements and bugfixes for every release of Mnesia. Each release of Mnesia thus constitutes one section in this document. The title of each section is the version number of Mnesia.

        Mnesia 4.25.3.1

        Fixed Bugs and Malfunctions

        Mnesia 4.25.3

        Fixed Bugs and Malfunctions

        • Added documentation for user_properties and functions read_table_property/2, write_table_property/2, delete_table_property. -Enhanced documentation for frag_properties.

          Own Id: OTP-20038 Aux Id: GH-10812, PR-10881

        • Fixed a bug where stacktrace was not returned from mnesia:transaction/1 when transaction aborts with an error exception.

          Own Id: OTP-20094 Aux Id: GH-10967, PR-11002

        Mnesia 4.25.2

        Improvements and New Features

        • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

          A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

          make release_docs places the documentation in the released code under the doc folder.

          make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

          The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

          Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

          Improves the source Software-Bill-of-Materials

          • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
          • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
          • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

          Own Id: OTP-19886 Aux Id: PR-10434

        Mnesia 4.25.1

        Fixed Bugs and Malfunctions

        • Fixed bug where mnesia:del_table_copy/3 could fail when deleting a node that had tables which was not active anywhere.

          Own Id: OTP-19890 Aux Id: ERIERL-1268, PR-10482

        Mnesia 4.25

        Fixed Bugs and Malfunctions

        • Add missing documentation about mnesia:activity/4

          Own Id: OTP-19769 Aux Id: PR-10186

        • With this change mnesia will try to not leak internal messages to user processes.

          Own Id: OTP-19855 Aux Id: GH-10347, PR-10379

        Improvements and New Features

        • The mnesia_registry module will be removed in Erlang/OTP 29.

          Own Id: OTP-19808 Aux Id: PR-10275

        Mnesia 4.24.1

        Fixed Bugs and Malfunctions

        • Mnesia no longer crashes when the node name is used as a table name.

          Own Id: OTP-19745 Aux Id: PR-10147

        Mnesia 4.24

        Improvements and New Features

        • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

          All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

          -type meter() :: integer().
          --type foot() :: integer().

          Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

          -nominal meter() :: integer().
          --nominal foot() :: integer().

          More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

          Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

          Own Id: OTP-19364 Aux Id: PR-9079

        • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

          Own Id: OTP-19575 Aux Id: PR-9670

        Mnesia 4.23.5.2

        Fixed Bugs and Malfunctions

        Mnesia 4.23.5.1

        Fixed Bugs and Malfunctions

        • Fixed bug where mnesia:del_table_copy/3 could fail when deleting a node that had tables which was not active anywhere.

          Own Id: OTP-19890 Aux Id: ERIERL-1268, PR-10482

        Mnesia 4.23.5

        Fixed Bugs and Malfunctions

        • With this change mnesia will merge schema of tables using external backends.

          Own Id: OTP-19437 Aux Id: PR-9534

        Mnesia 4.23.4

        Fixed Bugs and Malfunctions

        • Mnesia could fail to load a table, if one of the copy holders was moved during startup.

          Own Id: OTP-19501 Aux Id: ERIERL-1195, PR-9499

        Mnesia 4.23.3

        Fixed Bugs and Malfunctions

        • Mnesia table converted from ext_copies to disc_copies will now be properly saved to disk.

          Own Id: OTP-19292 Aux Id: PR-8921, GH-8706

        • Mnesia could crash if table was deleted during checkpoint initialization.

          Own Id: OTP-19368 Aux Id: ERIERL-1154, PR-9093

        Mnesia 4.23.2

        Fixed Bugs and Malfunctions

        • The mnesia_registry module have been deprecated.

          Own Id: OTP-18994

        Improvements and New Features

        • The documentation has been migrated to use Markdown and ExDoc.

          Own Id: OTP-18955 Aux Id: PR-8026

        Mnesia 4.23.1.2

        Fixed Bugs and Malfunctions

        • With this change mnesia will merge schema of tables using external backends.

          Own Id: OTP-19437 Aux Id: PR-9534

        • Mnesia could fail to load a table, if one of the copy holders was moved during startup.

          Own Id: OTP-19501 Aux Id: ERIERL-1195, PR-9499

        Mnesia 4.23.1.1

        Fixed Bugs and Malfunctions

        • Mnesia could crash if table was deleted during checkpoint initialization.

          Own Id: OTP-19368 Aux Id: ERIERL-1154, PR-9093

        Mnesia 4.23.1

        Fixed Bugs and Malfunctions

        • Mnesia could crash during startup if del_table_copy/2 and add_table_copy/3 was invoked when the table was loading.

          Own Id: OTP-19076 Aux Id: ERIERL-1073

        Mnesia 4.23

        Fixed Bugs and Malfunctions

        Mnesia 4.25.2

        Improvements and New Features

        • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

          A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

          make release_docs places the documentation in the released code under the doc folder.

          make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

          The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

          Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

          Improves the source Software-Bill-of-Materials

          • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
          • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
          • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

          Own Id: OTP-19886 Aux Id: PR-10434

        Mnesia 4.25.1

        Fixed Bugs and Malfunctions

        • Fixed bug where mnesia:del_table_copy/3 could fail when deleting a node that had tables which was not active anywhere.

          Own Id: OTP-19890 Aux Id: ERIERL-1268, PR-10482

        Mnesia 4.25

        Fixed Bugs and Malfunctions

        • Add missing documentation about mnesia:activity/4

          Own Id: OTP-19769 Aux Id: PR-10186

        • With this change mnesia will try to not leak internal messages to user processes.

          Own Id: OTP-19855 Aux Id: GH-10347, PR-10379

        Improvements and New Features

        • The mnesia_registry module will be removed in Erlang/OTP 29.

          Own Id: OTP-19808 Aux Id: PR-10275

        Mnesia 4.24.1

        Fixed Bugs and Malfunctions

        • Mnesia no longer crashes when the node name is used as a table name.

          Own Id: OTP-19745 Aux Id: PR-10147

        Mnesia 4.24

        Improvements and New Features

        • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

          All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

          -type meter() :: integer().
          +-type foot() :: integer().

          Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

          -nominal meter() :: integer().
          +-nominal foot() :: integer().

          More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

          Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

          Own Id: OTP-19364 Aux Id: PR-9079

        • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

          Own Id: OTP-19575 Aux Id: PR-9670

        Mnesia 4.23.5.2

        Fixed Bugs and Malfunctions

        Mnesia 4.23.5.1

        Fixed Bugs and Malfunctions

        • Fixed bug where mnesia:del_table_copy/3 could fail when deleting a node that had tables which was not active anywhere.

          Own Id: OTP-19890 Aux Id: ERIERL-1268, PR-10482

        Mnesia 4.23.5

        Fixed Bugs and Malfunctions

        • With this change mnesia will merge schema of tables using external backends.

          Own Id: OTP-19437 Aux Id: PR-9534

        Mnesia 4.23.4

        Fixed Bugs and Malfunctions

        • Mnesia could fail to load a table, if one of the copy holders was moved during startup.

          Own Id: OTP-19501 Aux Id: ERIERL-1195, PR-9499

        Mnesia 4.23.3

        Fixed Bugs and Malfunctions

        • Mnesia table converted from ext_copies to disc_copies will now be properly saved to disk.

          Own Id: OTP-19292 Aux Id: PR-8921, GH-8706

        • Mnesia could crash if table was deleted during checkpoint initialization.

          Own Id: OTP-19368 Aux Id: ERIERL-1154, PR-9093

        Mnesia 4.23.2

        Fixed Bugs and Malfunctions

        • The mnesia_registry module have been deprecated.

          Own Id: OTP-18994

        Improvements and New Features

        • The documentation has been migrated to use Markdown and ExDoc.

          Own Id: OTP-18955 Aux Id: PR-8026

        Mnesia 4.23.1.2

        Fixed Bugs and Malfunctions

        • With this change mnesia will merge schema of tables using external backends.

          Own Id: OTP-19437 Aux Id: PR-9534

        • Mnesia could fail to load a table, if one of the copy holders was moved during startup.

          Own Id: OTP-19501 Aux Id: ERIERL-1195, PR-9499

        Mnesia 4.23.1.1

        Fixed Bugs and Malfunctions

        • Mnesia could crash if table was deleted during checkpoint initialization.

          Own Id: OTP-19368 Aux Id: ERIERL-1154, PR-9093

        Mnesia 4.23.1

        Fixed Bugs and Malfunctions

        • Mnesia could crash during startup if del_table_copy/2 and add_table_copy/3 was invoked when the table was loading.

          Own Id: OTP-19076 Aux Id: ERIERL-1073

        Mnesia 4.23

        Fixed Bugs and Malfunctions

        Improvements and New Features

        • Restore recreate of disc_only tables could crash if they had an index.

          Own Id: OTP-18843 Aux Id: GH-7766

        Mnesia 4.22.1

        Fixed Bugs and Malfunctions

        • Do not delete old backup file if the new backup fails.

          Own Id: OTP-18711 Aux Id: ERIERL-963

        Mnesia 4.22

        Improvements and New Features

        • Added debug statistics for active transactions.

          Own Id: OTP-18309 Aux Id: PR-6377

        • The implementation has been fixed to use proc_lib:init_fail/2,3 where appropriate, instead of proc_lib:init_ack/1,2.

          * POTENTIAL INCOMPATIBILITY *

          Own Id: OTP-18490 Aux Id: OTP-18471, GH-6339, PR-6843

        Mnesia 4.21.4.4

        Fixed Bugs and Malfunctions

        • Mnesia could fail to load a table, if one of the copy holders was moved during startup.

          Own Id: OTP-19501 Aux Id: ERIERL-1195, PR-9499

        Mnesia 4.21.4.3

        Fixed Bugs and Malfunctions

        • Mnesia could crash during startup if del_table_copy/2 and add_table_copy/3 was invoked when the table was loading.

          Own Id: OTP-19076 Aux Id: ERIERL-1073

        Mnesia 4.21.4.2

        Fixed Bugs and Malfunctions

        Mnesia 4.21.4.1

        Fixed Bugs and Malfunctions

        • Do not delete old backup file if the new backup fails.

          Own Id: OTP-18711 Aux Id: ERIERL-963

        Mnesia 4.21.4

        Fixed Bugs and Malfunctions

        • Improved consistency for dirty writes when a table was added with /usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/observer.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/observer.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/observer.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> observer - 2.18.2 - urn:uuid:81586da4-fc27-0039-e4a8-576c2608fb23 + urn:uuid:8fb6a003-fada-af01-008d-a85c6b182acd en - 2026-08-21T03:49:41Z + 2042-09-22T17:08:41Z /usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/observer.epub/OEBPS/ttb_ug.xhtml differs (HTML document, ASCII text, with very long lines (1157)) --- old//usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/observer.epub/OEBPS/ttb_ug.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/observer.epub/OEBPS/ttb_ug.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -46,116 +46,116 @@ text, but you can also write your own handler to make more complex interpretations of the trace information. A trace log can also be presented graphically with application Event Tracer (ET).

          If option format is specified to ttb:stop/1, the formatting is -automatically done when stopping ttb.

        Tracing Local Node from Erlang Shell

        The following small module is used in the subsequent example:

        -module(m).
        --export([f/0]).
        -f() ->
        +automatically done when stopping ttb.

        Tracing Local Node from Erlang Shell

        The following small module is used in the subsequent example:

        -module(m).
        +-export([f/0]).
        +f() ->
            receive
        -      From when is_pid(From) ->
        -         Now = erlang:now(),
        -         From ! {self(),Now}
        +      From when is_pid(From) ->
        +         Now = erlang:now(),
        +         From ! {self(),Now}
            end.

        The following example shows the basic use of ttb from the Erlang shell. Default options are used both for starting the tracer and for formatting (the custom fetch directory is however provided). This gives a trace log named Node-ttb in the newly created directory, where Node is the node name. The default handler prints the formatted trace messages in the shell:

        (tiger@durin)47> %% First I spawn a process running my test function
        -(tiger@durin)47> Pid = spawn(m,f,[]).
        +(tiger@durin)47> Pid = spawn(m,f,[]).
         <0.125.0>
        -(tiger@durin)48>
        +(tiger@durin)48>
         (tiger@durin)48> %% Then I start a tracer...
        -(tiger@durin)48> ttb:tracer().
        -{ok,[tiger@durin]}
        -(tiger@durin)49>
        +(tiger@durin)48> ttb:tracer().
        +{ok,[tiger@durin]}
        +(tiger@durin)49>
         (tiger@durin)49> %% and activate the new process for tracing
         (tiger@durin)49> %% function calls and sent messages.
        -(tiger@durin)49> ttb:p(Pid,[call,send]).
        -{ok,[{<0.125.0>,[{matched,tiger@durin,1}]}]}
        -(tiger@durin)50>
        +(tiger@durin)49> ttb:p(Pid,[call,send]).
        +{ok,[{<0.125.0>,[{matched,tiger@durin,1}]}]}
        +(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> %% 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)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
         (tiger@durin)52> %% my new process)
        -(tiger@durin)52> Pid ! self().
        +(tiger@durin)52> Pid ! self().
         <0.72.0>
        -(tiger@durin)53>
        +(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([return, {fetch_dir, "fetch"}]).
        -{stopped, "fetch"}
        -(tiger@durin)54>
        +(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("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}
        -({<0.125.0>,{m,f,0},tiger@durin}) <0.72.0> !
        -{<0.125.0>,{1031,133451,667611}}
        +(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}
        +({<0.125.0>,{m,f,0},tiger@durin}) <0.72.0> !
        +{<0.125.0>,{1031,133451,667611}}
         ok

        Build Your Own Tool

        The following example shows a simple tool for "debug tracing", that is, tracing -of function calls with return values:

        -module(mydebug).
        --export([start/0,trc/1,stop/0,format/1]).
        --export([print/4]).
        +of function calls with return values:

        -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").
        +-include_lib("stdlib/include/ms_transform.hrl").
         %%% -------------Tool API-------------
         %%% ----------------------------------
         %%% Star the "mydebug" tool
        -start() ->
        +start() ->
             %% The options specify that the binary log shall be named
             %% <Node>-debug_log and that the print/4 function in this
             %% module shall be used as format handler
        -    ttb:tracer(all,[{file,"debug_log"},{handler,{{?MODULE,print},0}}]),
        +    ttb:tracer(all,[{file,"debug_log"},{handler,{{?MODULE,print},0}}]),
             %% All processes (existing and new) shall trace function calls
             %% 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).
        +    ttb:p(all,call).
         
         %%% Set trace pattern on function(s)
        -trc(M) when is_atom(M) ->
        -    trc({M,'_','_'});
        -trc({M,F}) when is_atom(M), is_atom(F) ->
        -    trc({M,F,'_'});
        -trc({M,F,_A}=MFA) when is_atom(M), is_atom(F) ->
        +trc(M) when is_atom(M) ->
        +    trc({M,'_','_'});
        +trc({M,F}) when is_atom(M), is_atom(F) ->
        +    trc({M,F,'_'});
        +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).
        +    MatchSpec = dbg:fun2ms(fun(_) -> return_trace() end),
        +    ttb:tpl(MFA,MatchSpec).
         
         %%% Format a binary trace log
        -format(Dir) ->
        -    ttb:format(Dir).
        +format(Dir) ->
        +    ttb:format(Dir).
         
         %%% Stop the "mydebug" tool
        -stop() ->
        -    ttb:stop(return).
        +stop() ->
        +    ttb:stop(return).
         
         %%% --------Internal functions--------
         %%% ----------------------------------
         %%% Format handler
        -print(_Out,end_of_trace,_TI,N) ->
        +print(_Out,end_of_trace,_TI,N) ->
             N;
        -print(Out,Trace,_TI,N) ->
        -    do_print(Out,Trace,N),
        +print(Out,Trace,_TI,N) ->
        +    do_print(Out,Trace,N),
             N+1.
         
        -do_print(Out,{trace_ts,P,call,{M,F,A},Ts},N) ->
        -    io:format(Out,
        +do_print(Out,{trace_ts,P,call,{M,F,A},Ts},N) ->
        +    io:format(Out,
                       "~w: ~w, ~w:~n"
                       "Call      : ~w:~w/~w~n"
                       "Arguments :~p~n~n",
        -              [N,Ts,P,M,F,length(A),A]);
        -do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
        -    io:format(Out,
        +              [N,Ts,P,M,F,length(A),A]);
        +do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
        +    io:format(Out,
                       "~w: ~w, ~w:~n"
                       "Return from  : ~w:~w/~w~n"
                       "Return value :~p~n~n",
        -              [N,Ts,P,M,F,A,R]).

        To distinguish trace logs produced with this tool from other logs, option file + [N,Ts,P,M,F,A,R]).

        To distinguish trace logs produced with this tool from other logs, option file is used in tracer/2. The logs are therefore fetched to a directory named ttb_upload_debug_log-YYYYMMDD-HHMMSS

        By using option handler when starting the tracer, the information about how to format the file is stored in the trace information file (.ti). This is not @@ -175,9 +175,9 @@ called on the traced node, the trace control node does not show. To start a hidden node, add option -hidden to the erl command, for example:

        % erl -sname trace_control -hidden

        Diskless Node

        If the traced node is diskless, ttb must be started from a trace control node with disk access, and option file must be specified to function tracer/2 -with value {local, File}, for example:

        (trace_control@durin)1> ttb:tracer(mynode@diskless,
        -                                   {file,{local,{wrap,"mytrace"}}}).
        -{ok,[mynode@diskless]}

        More Tracing Options

        When setting up a trace, the following features can also be activated:

        • Time-constrained tracing
        • Overload protection
        • Autoresume
        • dbg mode

        Time-Constrained Tracing

        It can sometimes be helpful to enable trace for a specified period of time (for +with value {local, File}, for example:

        (trace_control@durin)1> ttb:tracer(mynode@diskless,
        +                                   {file,{local,{wrap,"mytrace"}}}).
        +{ok,[mynode@diskless]}

        More Tracing Options

        When setting up a trace, the following features can also be activated:

        • Time-constrained tracing
        • Overload protection
        • Autoresume
        • dbg mode

        Time-Constrained Tracing

        It can sometimes be helpful to enable trace for a specified period of time (for example, to monitor a system for 24 hours or half a second). This can be done with option {timer, TimerSpec}. If TimerSpec has the form of MSec, the trace is stopped after MSec milliseconds using ttb:stop/0. If more options @@ -185,10 +185,10 @@ Opts as argument.

        The timer is started with ttb:p/2, so any trace patterns must be set up in advance. ttb:start_trace/4 always sets up all patterns before invoking ttb:p/2.

        The following example shows how to set up a trace that is automatically stopped -and formatted after 5 seconds:

        (tiger@durin)1> ttb:start_trace([node()],
        -                                [{erlang, now,[]}],
        -                                {all, call},
        -                                [{timer, {5000, format}}]).

        Note

        Because of network and processing delays, the period of tracing is +and formatted after 5 seconds:

        (tiger@durin)1> ttb:start_trace([node()],
        +                                [{erlang, now,[]}],
        +                                {all, call},
        +                                [{timer, {5000, format}}]).

        Note

        Because of network and processing delays, the period of tracing is approximate.

        Overload Protection

        When tracing live systems, always take special care to not overload a node with /usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/observer.epub/OEBPS/ttb.xhtml differs (HTML document, ASCII text, with very long lines (518)) --- old//usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/observer.epub/OEBPS/ttb.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/observer.epub/OEBPS/ttb.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -1808,13 +1808,13 @@ is "contaminated" with token seq_trace.

        If Flags = all, all possible flags are set.

        The possible values for SeqTraceFlag are available in seq_trace.

        For a description of the match_spec() syntax, see section Match Specifications in Erlang in ERTS, which explains the general match specification "language".

        Note

        The system tracer for sequential tracing is automatically initiated by ttb -when a trace port is started with ttb:tracer/0,1,2.

        An example of how to use function seq_trigger_ms/0,1 follows:

        (tiger@durin)5> ttb:tracer().
        -{ok,[tiger@durin]}
        -(tiger@durin)6> ttb:p(all,call).
        -{ok,{[all],[call]}}
        -(tiger@durin)7> ttb:tp(mod,func,ttb:seq_trigger_ms()).
        -{ok,[{matched,1},{saved,1}]}
        -(tiger@durin)8>

        Whenever mod:func(...) is called after this, token seq_trace is set on the +when a trace port is started with ttb:tracer/0,1,2.

        An example of how to use function seq_trigger_ms/0,1 follows:

        (tiger@durin)5> ttb:tracer().
        +{ok,[tiger@durin]}
        +(tiger@durin)6> ttb:p(all,call).
        +{ok,{[all],[call]}}
        +(tiger@durin)7> ttb:tp(mod,func,ttb:seq_trigger_ms()).
        +{ok,[{matched,1},{saved,1}]}
        +(tiger@durin)8>

        Whenever mod:func(...) is called after this, token seq_trace is set on the executing process.

      @@ -1853,14 +1853,14 @@

      This function is a shortcut allowing to start a trace with one command. Each tuple in Patterns is converted to a list, which in turn is passed to -ttb:tpl/2,3,4.

      The call:

      > ttb:start_trace([Node, OtherNode],
      -                  [{mod, foo, []}, {mod, bar, 2}],
      -                  {all, call},
      -                  [{file, File}, {handler,{fun myhandler/4, S}}]).

      is equivalent to:

      > 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).
      +ttb:tpl/2,3,4.

      The call:

      > ttb:start_trace([Node, OtherNode],
      +                  [{mod, foo, []}, {mod, bar, 2}],
      +                  {all, call},
      +                  [{file, File}, {handler,{fun myhandler/4, S}}]).

      is equivalent to:

      > 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).
      /usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/ttb.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/ttb.html 2026-08-21 04:00:25.818336390 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/ttb.html 2026-08-21 04:00:25.818336390 +0000 @@ -1895,13 +1895,13 @@ is "contaminated" with token seq_trace.

      If Flags = all, all possible flags are set.

      The possible values for SeqTraceFlag are available in seq_trace.

      For a description of the match_spec() syntax, see section Match Specifications in Erlang in ERTS, which explains the general match specification "language".

      Note

      The system tracer for sequential tracing is automatically initiated by ttb -when a trace port is started with ttb:tracer/0,1,2.

      An example of how to use function seq_trigger_ms/0,1 follows:

      (tiger@durin)5> ttb:tracer().
      -{ok,[tiger@durin]}
      -(tiger@durin)6> ttb:p(all,call).
      -{ok,{[all],[call]}}
      -(tiger@durin)7> ttb:tp(mod,func,ttb:seq_trigger_ms()).
      -{ok,[{matched,1},{saved,1}]}
      -(tiger@durin)8>

      Whenever mod:func(...) is called after this, token seq_trace is set on the +when a trace port is started with ttb:tracer/0,1,2.

      An example of how to use function seq_trigger_ms/0,1 follows:

      (tiger@durin)5> ttb:tracer().
      +{ok,[tiger@durin]}
      +(tiger@durin)6> ttb:p(all,call).
      +{ok,{[all],[call]}}
      +(tiger@durin)7> ttb:tp(mod,func,ttb:seq_trigger_ms()).
      +{ok,[{matched,1},{saved,1}]}
      +(tiger@durin)8>

      Whenever mod:func(...) is called after this, token seq_trace is set on the executing process.

      @@ -1940,14 +1940,14 @@

      This function is a shortcut allowing to start a trace with one command. Each tuple in Patterns is converted to a list, which in turn is passed to -ttb:tpl/2,3,4.

      The call:

      > ttb:start_trace([Node, OtherNode],
      -                  [{mod, foo, []}, {mod, bar, 2}],
      -                  {all, call},
      -                  [{file, File}, {handler,{fun myhandler/4, S}}]).

      is equivalent to:

      > 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).
      +ttb:tpl/2,3,4.

      The call:

      > ttb:start_trace([Node, OtherNode],
      +                  [{mod, foo, []}, {mod, bar, 2}],
      +                  {all, call},
      +                  [{file, File}, {handler,{fun myhandler/4, S}}]).

      is equivalent to:

      > 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).
      /usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/ttb_ug.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1157)) --- old//usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/ttb_ug.html 2026-08-21 04:00:25.853336618 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/observer-2.18.2/doc/html/ttb_ug.html 2026-08-21 04:00:25.853336618 +0000 @@ -118,116 +118,116 @@ text, but you can also write your own handler to make more complex interpretations of the trace information. A trace log can also be presented graphically with application Event Tracer (ET).

      If option format is specified to ttb:stop/1, the formatting is -automatically done when stopping ttb.

      Tracing Local Node from Erlang Shell

      The following small module is used in the subsequent example:

      -module(m).
      --export([f/0]).
      -f() ->
      +automatically done when stopping ttb.

      Tracing Local Node from Erlang Shell

      The following small module is used in the subsequent example:

      -module(m).
      +-export([f/0]).
      +f() ->
          receive
      -      From when is_pid(From) ->
      -         Now = erlang:now(),
      -         From ! {self(),Now}
      +      From when is_pid(From) ->
      +         Now = erlang:now(),
      +         From ! {self(),Now}
          end.

      The following example shows the basic use of ttb from the Erlang shell. Default options are used both for starting the tracer and for formatting (the custom fetch directory is however provided). This gives a trace log named Node-ttb in the newly created directory, where Node is the node name. The default handler prints the formatted trace messages in the shell:

      (tiger@durin)47> %% First I spawn a process running my test function
      -(tiger@durin)47> Pid = spawn(m,f,[]).
      +(tiger@durin)47> Pid = spawn(m,f,[]).
       <0.125.0>
      -(tiger@durin)48>
      +(tiger@durin)48>
       (tiger@durin)48> %% Then I start a tracer...
      -(tiger@durin)48> ttb:tracer().
      -{ok,[tiger@durin]}
      -(tiger@durin)49>
      +(tiger@durin)48> ttb:tracer().
      +{ok,[tiger@durin]}
      +(tiger@durin)49>
       (tiger@durin)49> %% and activate the new process for tracing
       (tiger@durin)49> %% function calls and sent messages.
      -(tiger@durin)49> ttb:p(Pid,[call,send]).
      -{ok,[{<0.125.0>,[{matched,tiger@durin,1}]}]}
      -(tiger@durin)50>
      +(tiger@durin)49> ttb:p(Pid,[call,send]).
      +{ok,[{<0.125.0>,[{matched,tiger@durin,1}]}]}
      +(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> %% 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)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
       (tiger@durin)52> %% my new process)
      -(tiger@durin)52> Pid ! self().
      +(tiger@durin)52> Pid ! self().
       <0.72.0>
      -(tiger@durin)53>
      +(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([return, {fetch_dir, "fetch"}]).
      -{stopped, "fetch"}
      -(tiger@durin)54>
      +(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("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}
      -({<0.125.0>,{m,f,0},tiger@durin}) <0.72.0> !
      -{<0.125.0>,{1031,133451,667611}}
      +(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}
      +({<0.125.0>,{m,f,0},tiger@durin}) <0.72.0> !
      +{<0.125.0>,{1031,133451,667611}}
       ok

      Build Your Own Tool

      The following example shows a simple tool for "debug tracing", that is, tracing -of function calls with return values:

      -module(mydebug).
      --export([start/0,trc/1,stop/0,format/1]).
      --export([print/4]).
      +of function calls with return values:

      -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").
      +-include_lib("stdlib/include/ms_transform.hrl").
       %%% -------------Tool API-------------
       %%% ----------------------------------
       %%% Star the "mydebug" tool
      -start() ->
      +start() ->
           %% The options specify that the binary log shall be named
           %% <Node>-debug_log and that the print/4 function in this
           %% module shall be used as format handler
      -    ttb:tracer(all,[{file,"debug_log"},{handler,{{?MODULE,print},0}}]),
      +    ttb:tracer(all,[{file,"debug_log"},{handler,{{?MODULE,print},0}}]),
           %% All processes (existing and new) shall trace function calls
           %% 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).
      +    ttb:p(all,call).
       
       %%% Set trace pattern on function(s)
      -trc(M) when is_atom(M) ->
      -    trc({M,'_','_'});
      -trc({M,F}) when is_atom(M), is_atom(F) ->
      -    trc({M,F,'_'});
      -trc({M,F,_A}=MFA) when is_atom(M), is_atom(F) ->
      +trc(M) when is_atom(M) ->
      +    trc({M,'_','_'});
      +trc({M,F}) when is_atom(M), is_atom(F) ->
      +    trc({M,F,'_'});
      +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).
      +    MatchSpec = dbg:fun2ms(fun(_) -> return_trace() end),
      +    ttb:tpl(MFA,MatchSpec).
       
       %%% Format a binary trace log
      -format(Dir) ->
      -    ttb:format(Dir).
      +format(Dir) ->
      +    ttb:format(Dir).
       
       %%% Stop the "mydebug" tool
      -stop() ->
      -    ttb:stop(return).
      +stop() ->
      +    ttb:stop(return).
       
       %%% --------Internal functions--------
       %%% ----------------------------------
       %%% Format handler
      -print(_Out,end_of_trace,_TI,N) ->
      +print(_Out,end_of_trace,_TI,N) ->
           N;
      -print(Out,Trace,_TI,N) ->
      -    do_print(Out,Trace,N),
      +print(Out,Trace,_TI,N) ->
      +    do_print(Out,Trace,N),
           N+1.
       
      -do_print(Out,{trace_ts,P,call,{M,F,A},Ts},N) ->
      -    io:format(Out,
      +do_print(Out,{trace_ts,P,call,{M,F,A},Ts},N) ->
      +    io:format(Out,
                     "~w: ~w, ~w:~n"
                     "Call      : ~w:~w/~w~n"
                     "Arguments :~p~n~n",
      -              [N,Ts,P,M,F,length(A),A]);
      -do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
      -    io:format(Out,
      +              [N,Ts,P,M,F,length(A),A]);
      +do_print(Out,{trace_ts,P,return_from,{M,F,A},R,Ts},N) ->
      +    io:format(Out,
                     "~w: ~w, ~w:~n"
                     "Return from  : ~w:~w/~w~n"
                     "Return value :~p~n~n",
      -              [N,Ts,P,M,F,A,R]).

      To distinguish trace logs produced with this tool from other logs, option file + [N,Ts,P,M,F,A,R]).

      To distinguish trace logs produced with this tool from other logs, option file is used in tracer/2. The logs are therefore fetched to a directory named ttb_upload_debug_log-YYYYMMDD-HHMMSS

      By using option handler when starting the tracer, the information about how to format the file is stored in the trace information file (.ti). This is not @@ -247,9 +247,9 @@ called on the traced node, the trace control node does not show. To start a hidden node, add option -hidden to the erl command, for example:

      % erl -sname trace_control -hidden

      Diskless Node

      If the traced node is diskless, ttb must be started from a trace control node with disk access, and option file must be specified to function tracer/2 -with value {local, File}, for example:

      (trace_control@durin)1> ttb:tracer(mynode@diskless,
      -                                   {file,{local,{wrap,"mytrace"}}}).
      -{ok,[mynode@diskless]}

      More Tracing Options

      When setting up a trace, the following features can also be activated:

      • Time-constrained tracing
      • Overload protection
      • Autoresume
      • dbg mode

      Time-Constrained Tracing

      It can sometimes be helpful to enable trace for a specified period of time (for +with value {local, File}, for example:

      (trace_control@durin)1> ttb:tracer(mynode@diskless,
      +                                   {file,{local,{wrap,"mytrace"}}}).
      +{ok,[mynode@diskless]}

      More Tracing Options

      When setting up a trace, the following features can also be activated:

      • Time-constrained tracing
      • Overload protection
      • Autoresume
      • dbg mode

      Time-Constrained Tracing

      It can sometimes be helpful to enable trace for a specified period of time (for example, to monitor a system for 24 hours or half a second). This can be done with option {timer, TimerSpec}. If TimerSpec has the form of MSec, the trace is stopped after MSec milliseconds using ttb:stop/0. If more options @@ -257,10 +257,10 @@ Opts as argument.

      The timer is started with ttb:p/2, so any trace patterns must be set up in advance. ttb:start_trace/4 always sets up all patterns before invoking ttb:p/2.

      The following example shows how to set up a trace that is automatically stopped -and formatted after 5 seconds:

      (tiger@durin)1> ttb:start_trace([node()],
      -                                [{erlang, now,[]}],
      -                                {all, call},
      -                                [{timer, {5000, format}}]).

      Note

      Because of network and processing delays, the period of tracing is +and formatted after 5 seconds:

      (tiger@durin)1> ttb:start_trace([node()],
      +                                [{erlang, now,[]}],
      +                                {all, call},
      +                                [{timer, {5000, format}}]).

      Note

      Because of network and processing delays, the period of tracing is approximate.

      Overload Protection

      When tracing live systems, always take special care to not overload a node with /usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/getting_started.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1738)) --- old//usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/getting_started.html 2026-08-21 04:00:25.878336780 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/getting_started.html 2026-08-21 04:00:25.878336780 +0000 @@ -109,77 +109,77 @@ relevance to anything that exist in reality, it is just a simple example. The example was created using sqlserver 7.0 with servicepack 1 as database and the ODBC driver for sqlserver with version 2000.80.194.00.

       1 > odbc:start().
      -      ok

      Connect to the database

       2 > {ok, Ref} = odbc:connect("DSN=sql-server;UID=aladdin;PWD=sesame", []).
      -      {ok,<0.342.0>}

      Create a table

       3 > odbc:sql_query(Ref, "CREATE TABLE EMPLOYEE (NR integer,
      +      ok

      Connect to the database

       2 > {ok, Ref} = odbc:connect("DSN=sql-server;UID=aladdin;PWD=sesame", []).
      +      {ok,<0.342.0>}

      Create a table

       3 > odbc:sql_query(Ref, "CREATE TABLE EMPLOYEE (NR integer,
             FIRSTNAME  char varying(20), LASTNAME  char varying(20), GENDER char(1),
             PRIMARY KEY(NR))").
             {updated,undefined}

      Insert some data

       4 > odbc:sql_query(Ref, "INSERT INTO EMPLOYEE VALUES(1, 'Jane', 'Doe', 'F')").
             {updated,1}

      Check what data types the database assigned for the columns. Hopefully this is not a surprise, some times it can be! These are the data types that you should -use if you want to do a parameterized query.

       5 > odbc:describe_table(Ref, "EMPLOYEE").
      -      {ok, [{"NR", sql_integer},
      -            {"FIRSTNAME", {sql_varchar, 20}},
      -            {"LASTNAME", {sql_varchar, 20}}
      -            {"GENDER", {sql_char, 1}}]}

      Use a parameterized query to insert many rows in one go.

       6 > odbc:param_query(Ref,"INSERT INTO EMPLOYEE (NR, FIRSTNAME, "
      +use if you want to do a parameterized query.

       5 > odbc:describe_table(Ref, "EMPLOYEE").
      +      {ok, [{"NR", sql_integer},
      +            {"FIRSTNAME", {sql_varchar, 20}},
      +            {"LASTNAME", {sql_varchar, 20}}
      +            {"GENDER", {sql_char, 1}}]}

      Use a parameterized query to insert many rows in one go.

       6 > odbc:param_query(Ref,"INSERT INTO EMPLOYEE (NR, FIRSTNAME, "
                         "LASTNAME, GENDER) VALUES(?, ?, ?, ?)",
      -                   [{sql_integer,[2,3,4,5,6,7,8]},
      -                    {{sql_varchar, 20},
      -                             ["John", "Monica", "Ross", "Rachel",
      -                             "Piper", "Prue", "Louise"]},
      -                   {{sql_varchar, 20},
      -                             ["Doe","Geller","Geller", "Green",
      -                              "Halliwell", "Halliwell", "Lane"]},
      -                   {{sql_char, 1}, ["M","F","M","F","F","F","F"]}]).
      -      {updated, 7}

      Fetch all data in the table employee

       7> odbc:sql_query(Ref, "SELECT * FROM EMPLOYEE").
      -    {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],
      -          [{1,"Jane","Doe","F"},
      -           {2,"John","Doe","M"},
      -           {3,"Monica","Geller","F"},
      -           {4,"Ross","Geller","M"},
      -           {5,"Rachel","Green","F"},
      -           {6,"Piper","Halliwell","F"},
      -           {7,"Prue","Halliwell","F"},
      -           {8,"Louise","Lane","F"}]]}

      Associate a result set containing the whole table EMPLOYEE to the connection. -The number of rows in the result set is returned.

       8 > odbc:select_count(Ref, "SELECT * FROM EMPLOYEE").
      -      {ok,8}

      You can always traverse the result set sequential by using next

       9 > odbc:next(Ref).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{1,"Jane","Doe","F"}]}
       10 > odbc:next(Ref).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{2,"John","Doe","M"}]}

      If your driver supports scrollable cursors you have a little more freedom, and -can do things like this.

       11 > odbc:last(Ref).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{8,"Louise","Lane","F"}]}
       12 > odbc:prev(Ref).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{7,"Prue","Halliwell","F"}]}
       13 > odbc:first(Ref).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{1,"Jane","Doe","F"}]}
       14 > odbc:next(Ref).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{2,"John","Doe","M"}]}

      Fetch the fields FIRSTNAMEand NRfor all female employees

       15 > odbc:sql_query(Ref, "SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = &#href_anchor"p" data-group-id="8871805270-1">).
      -     {selected,["FIRSTNAME","NR"],
      -          [{"Jane",1},
      -           {"Monica",3},
      -           {"Rachel",5},
      -           {"Piper",6},
      -           {"Prue",7},
      -           {"Louise",8}]}

      Fetch the fields FIRSTNAMEand NRfor all female employees and sort them on -the field FIRSTNAME.

       16 > odbc:sql_query(Ref, "SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'
      -      ORDER BY FIRSTNAME").
      -    {selected,["FIRSTNAME","NR"],
      -          [{"Jane",1},
      -           {"Louise",8},
      -           {"Monica",3},
      -           {"Piper",6},
      -           {"Prue",7},
      -           {"Rachel",5}]}

      Associate a result set that contains the fields FIRSTNAME and NRfor all + [{sql_integer,[2,3,4,5,6,7,8]}, + {{sql_varchar, 20}, + ["John", "Monica", "Ross", "Rachel", + "Piper", "Prue", "Louise"]}, + {{sql_varchar, 20}, + ["Doe","Geller","Geller", "Green", + "Halliwell", "Halliwell", "Lane"]}, + {{sql_char, 1}, ["M","F","M","F","F","F","F"]}]). + {updated, 7}

      Fetch all data in the table employee

       7> odbc:sql_query(Ref, "SELECT * FROM EMPLOYEE").
      +    {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],
      +          [{1,"Jane","Doe","F"},
      +           {2,"John","Doe","M"},
      +           {3,"Monica","Geller","F"},
      +           {4,"Ross","Geller","M"},
      +           {5,"Rachel","Green","F"},
      +           {6,"Piper","Halliwell","F"},
      +           {7,"Prue","Halliwell","F"},
      +           {8,"Louise","Lane","F"}]]}

      Associate a result set containing the whole table EMPLOYEE to the connection. +The number of rows in the result set is returned.

       8 > odbc:select_count(Ref, "SELECT * FROM EMPLOYEE").
      +      {ok,8}

      You can always traverse the result set sequential by using next

       9 > odbc:next(Ref).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{1,"Jane","Doe","F"}]}
       10 > odbc:next(Ref).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{2,"John","Doe","M"}]}

      If your driver supports scrollable cursors you have a little more freedom, and +can do things like this.

       11 > odbc:last(Ref).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{8,"Louise","Lane","F"}]}
       12 > odbc:prev(Ref).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{7,"Prue","Halliwell","F"}]}
       13 > odbc:first(Ref).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{1,"Jane","Doe","F"}]}
       14 > odbc:next(Ref).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{2,"John","Doe","M"}]}

      Fetch the fields FIRSTNAMEand NRfor all female employees

       15 > odbc:sql_query(Ref, "SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = &#href_anchor"p" data-group-id="7788528084-1">).
      +     {selected,["FIRSTNAME","NR"],
      +          [{"Jane",1},
      +           {"Monica",3},
      +           {"Rachel",5},
      +           {"Piper",6},
      +           {"Prue",7},
      +           {"Louise",8}]}

      Fetch the fields FIRSTNAMEand NRfor all female employees and sort them on +the field FIRSTNAME.

       16 > odbc:sql_query(Ref, "SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'
      +      ORDER BY FIRSTNAME").
      +    {selected,["FIRSTNAME","NR"],
      +          [{"Jane",1},
      +           {"Louise",8},
      +           {"Monica",3},
      +           {"Piper",6},
      +           {"Prue",7},
      +           {"Rachel",5}]}

      Associate a result set that contains the fields FIRSTNAME and NRfor all female employees to the connection. The number of rows in the result set is -returned.

       17 > odbc:select_count(Ref, "SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'").
      -      {ok,6}

      A few more ways of retrieving parts of the result set when the driver supports +returned.

       17 > odbc:select_count(Ref, "SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'").
      +      {ok,6}

      A few more ways of retrieving parts of the result set when the driver supports scrollable cursors. Note that next will work even without support for scrollable -cursors.

       18 > odbc:select(Ref, {relative, 2}, 3).
      -    {selected,["FIRSTNAME","NR"],[{"Monica",3},{"Rachel",5},{"Piper",6}]}
       19 > odbc:select(Ref, next, 2).
      -      {selected,["FIRSTNAME","NR"],[{"Prue",7},{"Louise",8}]}
       20 > odbc:select(Ref, {absolute, 1}, 2).
      -      {selected,["FIRSTNAME","NR"],[{"Jane",1},{"Monica",3}]}
       21 > odbc:select(Ref, next, 2).
      -    {selected,["FIRSTNAME","NR"],[{"Rachel",5},{"Piper",6}]}
       22 > odbc:select(Ref, {absolute, 1}, 4).
      -      {selected,["FIRSTNAME","NR"],
      -                [{"Jane",1},{"Monica",3},{"Rachel",5},{"Piper",6}]}

      Select, using a parameterized query.

       23 > odbc:param_query(Ref, "SELECT * FROM EMPLOYEE WHERE GENDER=?",
      -      [{{sql_char, 1}, ["M"]}]).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],
      -                [{2,"John", "Doe", "M"},{4,"Ross","Geller","M"}]}

      Delete the table EMPLOYEE.

       24 > odbc:sql_query(Ref, "DROP TABLE EMPLOYEE").
      -      {updated,undefined}

      Shut down the connection.

       25 > odbc:disconnect(Ref).
      +cursors.

       18 > odbc:select(Ref, {relative, 2}, 3).
      +    {selected,["FIRSTNAME","NR"],[{"Monica",3},{"Rachel",5},{"Piper",6}]}
       19 > odbc:select(Ref, next, 2).
      +      {selected,["FIRSTNAME","NR"],[{"Prue",7},{"Louise",8}]}
       20 > odbc:select(Ref, {absolute, 1}, 2).
      +      {selected,["FIRSTNAME","NR"],[{"Jane",1},{"Monica",3}]}
       21 > odbc:select(Ref, next, 2).
      +    {selected,["FIRSTNAME","NR"],[{"Rachel",5},{"Piper",6}]}
       22 > odbc:select(Ref, {absolute, 1}, 4).
      +      {selected,["FIRSTNAME","NR"],
      +                [{"Jane",1},{"Monica",3},{"Rachel",5},{"Piper",6}]}

      Select, using a parameterized query.

       23 > odbc:param_query(Ref, "SELECT * FROM EMPLOYEE WHERE GENDER=?",
      +      [{{sql_char, 1}, ["M"]}]).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],
      +                [{2,"John", "Doe", "M"},{4,"Ross","Geller","M"}]}

      Delete the table EMPLOYEE.

       24 > odbc:sql_query(Ref, "DROP TABLE EMPLOYEE").
      +      {updated,undefined}

      Shut down the connection.

       25 > odbc:disconnect(Ref).
             ok

      Shut down the application.

       26 > odbc:stop().
           =INFO REPORT==== 7-Jan-2004::17:00:59 ===
           application: odbc
      /usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/odbc.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text)
      --- old//usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/odbc.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/odbc.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
      @@ -4,10 +4,10 @@
                version="3.0">
         
           odbc - 2.16.1
      -    urn:uuid:2490f6d3-abbf-4703-5079-524eaff583a7
      +    urn:uuid:34325545-af61-0045-8fce-fe999647cd71
           en
       
      -    2026-08-21T03:49:42Z
      +    2042-09-22T17:08:42Z
       
         
         
      /usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/odbc.epub/OEBPS/getting_started.xhtml differs (HTML document, ASCII text, with very long lines (1738))
      --- old//usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/odbc.epub/OEBPS/getting_started.xhtml	2026-08-05 05:56:49.000000000 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/odbc-2.16.1/doc/html/odbc.epub/OEBPS/getting_started.xhtml	2026-08-05 05:56:49.000000000 +0000
      @@ -37,77 +37,77 @@
       relevance to anything that exist in reality, it is just a simple example. The
       example was created using sqlserver 7.0 with servicepack 1 as database and the
       ODBC driver for sqlserver with version 2000.80.194.00.

       1 > odbc:start().
      -      ok

      Connect to the database

       2 > {ok, Ref} = odbc:connect("DSN=sql-server;UID=aladdin;PWD=sesame", []).
      -      {ok,<0.342.0>}

      Create a table

       3 > odbc:sql_query(Ref, "CREATE TABLE EMPLOYEE (NR integer,
      +      ok

      Connect to the database

       2 > {ok, Ref} = odbc:connect("DSN=sql-server;UID=aladdin;PWD=sesame", []).
      +      {ok,<0.342.0>}

      Create a table

       3 > odbc:sql_query(Ref, "CREATE TABLE EMPLOYEE (NR integer,
             FIRSTNAME  char varying(20), LASTNAME  char varying(20), GENDER char(1),
             PRIMARY KEY(NR))").
             {updated,undefined}

      Insert some data

       4 > odbc:sql_query(Ref, "INSERT INTO EMPLOYEE VALUES(1, 'Jane', 'Doe', 'F')").
             {updated,1}

      Check what data types the database assigned for the columns. Hopefully this is not a surprise, some times it can be! These are the data types that you should -use if you want to do a parameterized query.

       5 > odbc:describe_table(Ref, "EMPLOYEE").
      -      {ok, [{"NR", sql_integer},
      -            {"FIRSTNAME", {sql_varchar, 20}},
      -            {"LASTNAME", {sql_varchar, 20}}
      -            {"GENDER", {sql_char, 1}}]}

      Use a parameterized query to insert many rows in one go.

       6 > odbc:param_query(Ref,"INSERT INTO EMPLOYEE (NR, FIRSTNAME, "
      +use if you want to do a parameterized query.

       5 > odbc:describe_table(Ref, "EMPLOYEE").
      +      {ok, [{"NR", sql_integer},
      +            {"FIRSTNAME", {sql_varchar, 20}},
      +            {"LASTNAME", {sql_varchar, 20}}
      +            {"GENDER", {sql_char, 1}}]}

      Use a parameterized query to insert many rows in one go.

       6 > odbc:param_query(Ref,"INSERT INTO EMPLOYEE (NR, FIRSTNAME, "
                         "LASTNAME, GENDER) VALUES(?, ?, ?, ?)",
      -                   [{sql_integer,[2,3,4,5,6,7,8]},
      -                    {{sql_varchar, 20},
      -                             ["John", "Monica", "Ross", "Rachel",
      -                             "Piper", "Prue", "Louise"]},
      -                   {{sql_varchar, 20},
      -                             ["Doe","Geller","Geller", "Green",
      -                              "Halliwell", "Halliwell", "Lane"]},
      -                   {{sql_char, 1}, ["M","F","M","F","F","F","F"]}]).
      -      {updated, 7}

      Fetch all data in the table employee

       7> odbc:sql_query(Ref, "SELECT * FROM EMPLOYEE").
      -    {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],
      -          [{1,"Jane","Doe","F"},
      -           {2,"John","Doe","M"},
      -           {3,"Monica","Geller","F"},
      -           {4,"Ross","Geller","M"},
      -           {5,"Rachel","Green","F"},
      -           {6,"Piper","Halliwell","F"},
      -           {7,"Prue","Halliwell","F"},
      -           {8,"Louise","Lane","F"}]]}

      Associate a result set containing the whole table EMPLOYEE to the connection. -The number of rows in the result set is returned.

       8 > odbc:select_count(Ref, "SELECT * FROM EMPLOYEE").
      -      {ok,8}

      You can always traverse the result set sequential by using next

       9 > odbc:next(Ref).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{1,"Jane","Doe","F"}]}
       10 > odbc:next(Ref).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{2,"John","Doe","M"}]}

      If your driver supports scrollable cursors you have a little more freedom, and -can do things like this.

       11 > odbc:last(Ref).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{8,"Louise","Lane","F"}]}
       12 > odbc:prev(Ref).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{7,"Prue","Halliwell","F"}]}
       13 > odbc:first(Ref).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{1,"Jane","Doe","F"}]}
       14 > odbc:next(Ref).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{2,"John","Doe","M"}]}

      Fetch the fields FIRSTNAMEand NRfor all female employees

       15 > odbc:sql_query(Ref, "SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'").
      -     {selected,["FIRSTNAME","NR"],
      -          [{"Jane",1},
      -           {"Monica",3},
      -           {"Rachel",5},
      -           {"Piper",6},
      -           {"Prue",7},
      -           {"Louise",8}]}

      Fetch the fields FIRSTNAMEand NRfor all female employees and sort them on -the field FIRSTNAME.

       16 > odbc:sql_query(Ref, "SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'
      -      ORDER BY FIRSTNAME").
      -    {selected,["FIRSTNAME","NR"],
      -          [{"Jane",1},
      -           {"Louise",8},
      -           {"Monica",3},
      -           {"Piper",6},
      -           {"Prue",7},
      -           {"Rachel",5}]}

      Associate a result set that contains the fields FIRSTNAME and NRfor all + [{sql_integer,[2,3,4,5,6,7,8]}, + {{sql_varchar, 20}, + ["John", "Monica", "Ross", "Rachel", + "Piper", "Prue", "Louise"]}, + {{sql_varchar, 20}, + ["Doe","Geller","Geller", "Green", + "Halliwell", "Halliwell", "Lane"]}, + {{sql_char, 1}, ["M","F","M","F","F","F","F"]}]). + {updated, 7}

      Fetch all data in the table employee

       7> odbc:sql_query(Ref, "SELECT * FROM EMPLOYEE").
      +    {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],
      +          [{1,"Jane","Doe","F"},
      +           {2,"John","Doe","M"},
      +           {3,"Monica","Geller","F"},
      +           {4,"Ross","Geller","M"},
      +           {5,"Rachel","Green","F"},
      +           {6,"Piper","Halliwell","F"},
      +           {7,"Prue","Halliwell","F"},
      +           {8,"Louise","Lane","F"}]]}

      Associate a result set containing the whole table EMPLOYEE to the connection. +The number of rows in the result set is returned.

       8 > odbc:select_count(Ref, "SELECT * FROM EMPLOYEE").
      +      {ok,8}

      You can always traverse the result set sequential by using next

       9 > odbc:next(Ref).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{1,"Jane","Doe","F"}]}
       10 > odbc:next(Ref).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{2,"John","Doe","M"}]}

      If your driver supports scrollable cursors you have a little more freedom, and +can do things like this.

       11 > odbc:last(Ref).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{8,"Louise","Lane","F"}]}
       12 > odbc:prev(Ref).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{7,"Prue","Halliwell","F"}]}
       13 > odbc:first(Ref).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{1,"Jane","Doe","F"}]}
       14 > odbc:next(Ref).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],[{2,"John","Doe","M"}]}

      Fetch the fields FIRSTNAMEand NRfor all female employees

       15 > odbc:sql_query(Ref, "SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'").
      +     {selected,["FIRSTNAME","NR"],
      +          [{"Jane",1},
      +           {"Monica",3},
      +           {"Rachel",5},
      +           {"Piper",6},
      +           {"Prue",7},
      +           {"Louise",8}]}

      Fetch the fields FIRSTNAMEand NRfor all female employees and sort them on +the field FIRSTNAME.

       16 > odbc:sql_query(Ref, "SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'
      +      ORDER BY FIRSTNAME").
      +    {selected,["FIRSTNAME","NR"],
      +          [{"Jane",1},
      +           {"Louise",8},
      +           {"Monica",3},
      +           {"Piper",6},
      +           {"Prue",7},
      +           {"Rachel",5}]}

      Associate a result set that contains the fields FIRSTNAME and NRfor all female employees to the connection. The number of rows in the result set is -returned.

       17 > odbc:select_count(Ref, "SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'").
      -      {ok,6}

      A few more ways of retrieving parts of the result set when the driver supports +returned.

       17 > odbc:select_count(Ref, "SELECT FIRSTNAME, NR FROM EMPLOYEE WHERE GENDER = 'F'").
      +      {ok,6}

      A few more ways of retrieving parts of the result set when the driver supports scrollable cursors. Note that next will work even without support for scrollable -cursors.

       18 > odbc:select(Ref, {relative, 2}, 3).
      -    {selected,["FIRSTNAME","NR"],[{"Monica",3},{"Rachel",5},{"Piper",6}]}
       19 > odbc:select(Ref, next, 2).
      -      {selected,["FIRSTNAME","NR"],[{"Prue",7},{"Louise",8}]}
       20 > odbc:select(Ref, {absolute, 1}, 2).
      -      {selected,["FIRSTNAME","NR"],[{"Jane",1},{"Monica",3}]}
       21 > odbc:select(Ref, next, 2).
      -    {selected,["FIRSTNAME","NR"],[{"Rachel",5},{"Piper",6}]}
       22 > odbc:select(Ref, {absolute, 1}, 4).
      -      {selected,["FIRSTNAME","NR"],
      -                [{"Jane",1},{"Monica",3},{"Rachel",5},{"Piper",6}]}

      Select, using a parameterized query.

       23 > odbc:param_query(Ref, "SELECT * FROM EMPLOYEE WHERE GENDER=?",
      -      [{{sql_char, 1}, ["M"]}]).
      -      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],
      -                [{2,"John", "Doe", "M"},{4,"Ross","Geller","M"}]}

      Delete the table EMPLOYEE.

       24 > odbc:sql_query(Ref, "DROP TABLE EMPLOYEE").
      -      {updated,undefined}

      Shut down the connection.

       25 > odbc:disconnect(Ref).
      +cursors.

       18 > odbc:select(Ref, {relative, 2}, 3).
      +    {selected,["FIRSTNAME","NR"],[{"Monica",3},{"Rachel",5},{"Piper",6}]}
       19 > odbc:select(Ref, next, 2).
      +      {selected,["FIRSTNAME","NR"],[{"Prue",7},{"Louise",8}]}
       20 > odbc:select(Ref, {absolute, 1}, 2).
      +      {selected,["FIRSTNAME","NR"],[{"Jane",1},{"Monica",3}]}
       21 > odbc:select(Ref, next, 2).
      +    {selected,["FIRSTNAME","NR"],[{"Rachel",5},{"Piper",6}]}
       22 > odbc:select(Ref, {absolute, 1}, 4).
      +      {selected,["FIRSTNAME","NR"],
      +                [{"Jane",1},{"Monica",3},{"Rachel",5},{"Piper",6}]}

      Select, using a parameterized query.

       23 > odbc:param_query(Ref, "SELECT * FROM EMPLOYEE WHERE GENDER=?",
      +      [{{sql_char, 1}, ["M"]}]).
      +      {selected,["NR","FIRSTNAME","LASTNAME","GENDER"],
      +                [{2,"John", "Doe", "M"},{4,"Ross","Geller","M"}]}

      Delete the table EMPLOYEE.

       24 > odbc:sql_query(Ref, "DROP TABLE EMPLOYEE").
      +      {updated,undefined}

      Shut down the connection.

       25 > odbc:disconnect(Ref).
             ok

      Shut down the application.

       26 > odbc:stop().
           =INFO REPORT==== 7-Jan-2004::17:00:59 ===
           application: odbc
      /usr/share/doc/packages/erlang-doc/lib/os_mon-2.11.2/doc/html/os_mon.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text)
      --- old//usr/share/doc/packages/erlang-doc/lib/os_mon-2.11.2/doc/html/os_mon.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/os_mon-2.11.2/doc/html/os_mon.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
      @@ -4,10 +4,10 @@
                version="3.0">
         
           os_mon - 2.11.2
      -    urn:uuid:2d9f2087-0b66-dad6-74c3-b6865671f810
      +    urn:uuid:aec06f00-a63e-42e9-db67-1a4d7b24450b
           en
       
      -    2026-08-21T03:49:30Z
      +    2042-09-22T17:08:29Z
       
         
         
      /usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/leex.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2158))
      --- old//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/leex.html	2026-08-21 04:00:26.018337692 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/leex.html	2026-08-21 04:00:26.018337692 +0000
      @@ -126,13 +126,13 @@
       next token. Note that pushing back a newline will mean the line numbering will
       no longer be correct.

      Note

      Pushing back characters gives you unexpected possibilities to cause the scanner to loop!

      The following example would match a simple Erlang integer or float and return a -token which could be sent to the Erlang parser:

      D = [0-9]
      +token which could be sent to the Erlang parser:

      D = [0-9]
       
      -{D}+ :
      -  {token,{integer,TokenLine,list_to_integer(TokenChars)}}.
      +{D}+ :
      +  {token,{integer,TokenLine,list_to_integer(TokenChars)}}.
       
      -{D}+\.{D}+((E|e)(\+|\-)?{D}+)? :
      -  {token,{float,TokenLine,list_to_float(TokenChars)}}.

      The Erlang code in the Erlang code. section is written into the output file +{D}+\.{D}+((E|e)(\+|\-)?{D}+)? : + {token,{float,TokenLine,list_to_float(TokenChars)}}.

      The Erlang code in the Erlang code. section is written into the output file directly after the module declaration and predefined exports declaration, making it possible to add extra exports, define imports, and other attributes, which are visible in the whole file.

      Regular Expressions

      The regular expressions allowed here is a subset of the set found in egrep and @@ -678,7 +678,7 @@ the token. This is continued until a token has been scanned. Cont is initially [].

      It is not designed to be called directly by an application, but is used through the I/O system where it can typically be called in an -application by:

      io:request(InFile, {get_until,unicode,Prompt,Module,token,[Loc]})
      +application by:

      io:request(InFile, {get_until,unicode,Prompt,Module,token,[Loc]})
         -> TokenRet
      @@ -767,7 +767,7 @@ like Erlang where there is an explicit end token, '.'. If no end token is found then the whole file will be scanned and returned. If an error occurs then all tokens up to and including the next end token will be skipped.

      It is not designed to be called directly by an application, but used through the -I/O system where it can typically be called in an application by:

      io:request(InFile, {get_until,unicode,Prompt,Module,tokens,[Loc]})
      +I/O system where it can typically be called in an application by:

      io:request(InFile, {get_until,unicode,Prompt,Module,tokens,[Loc]})
         -> TokensRet
      /usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (4188)) --- old//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/notes.html 2026-08-21 04:00:26.040337835 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/notes.html 2026-08-21 04:00:26.045337867 +0000 @@ -89,9 +89,9 @@ -

      This document describes the changes made to the Parsetools application.

      Parsetools 2.7.1

      Fixed Bugs and Malfunctions

      • The documentation for the token/3 and tokens/3 functions was corrected. The return value when there were too few characters is {more,Cont}.

        Own Id: OTP-19901 Aux Id: PR-10484

      Parsetools 2.7

      Improvements and New Features

      • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

        All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

        -type meter() :: integer().
        --type foot() :: integer().

        Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

        -nominal meter() :: integer().
        --nominal foot() :: integer().

        More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

        Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

        Own Id: OTP-19364 Aux Id: PR-9079

      • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

        Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      Parsetools 2.6

      Improvements and New Features

      • The leex documentation has been updated to use specs for documenting the generated interface.

        Own Id: OTP-18796 Aux Id: PR-7703

      • yecc now wraps the -module attribute with -file to indicate the .yrl source file.

        Own Id: OTP-18912 Aux Id: PR-7963

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      Parsetools 2.5

      Improvements and New Features

      • Leex has been extended with optional column number support.

        Own Id: OTP-18491 Aux Id: PR-6882

      Parsetools 2.4.1

      Improvements and New Features

      • There is a new configure option, --enable-deterministic-build, which will +

        This document describes the changes made to the Parsetools application.

        Parsetools 2.7.1

        Fixed Bugs and Malfunctions

        • The documentation for the token/3 and tokens/3 functions was corrected. The return value when there were too few characters is {more,Cont}.

          Own Id: OTP-19901 Aux Id: PR-10484

        Parsetools 2.7

        Improvements and New Features

        • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

          All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

          -type meter() :: integer().
          +-type foot() :: integer().

          Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

          -nominal meter() :: integer().
          +-nominal foot() :: integer().

          More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

          Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

          Own Id: OTP-19364 Aux Id: PR-9079

        • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

          Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

        • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

          Own Id: OTP-19575 Aux Id: PR-9670

        Parsetools 2.6

        Improvements and New Features

        • The leex documentation has been updated to use specs for documenting the generated interface.

          Own Id: OTP-18796 Aux Id: PR-7703

        • yecc now wraps the -module attribute with -file to indicate the .yrl source file.

          Own Id: OTP-18912 Aux Id: PR-7963

        • The documentation has been migrated to use Markdown and ExDoc.

          Own Id: OTP-18955 Aux Id: PR-8026

        Parsetools 2.5

        Improvements and New Features

        • Leex has been extended with optional column number support.

          Own Id: OTP-18491 Aux Id: PR-6882

        Parsetools 2.4.1

        Improvements and New Features

        • There is a new configure option, --enable-deterministic-build, which will apply the deterministic compiler option when building Erlang/OTP. The deterministic option has been improved to eliminate more sources of non-determinism in several applications.

          Own Id: OTP-18165 Aux Id: PR-5965

        Parsetools 2.4

        Improvements and New Features

        • In the generated code, yecc will now quote all atoms coming from terminals /usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> parsetools - 2.7.1 - urn:uuid:42fefa30-cdec-dc61-fb2a-ada87fca2772 + urn:uuid:809ef645-f3d9-0489-65ea-d22a2be096b0 en - 2026-08-21T03:47:52Z + 2042-09-22T17:06:32Z /usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub/OEBPS/leex.xhtml differs (HTML document, ASCII text, with very long lines (2158)) --- old//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub/OEBPS/leex.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub/OEBPS/leex.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -55,13 +55,13 @@ next token. Note that pushing back a newline will mean the line numbering will no longer be correct.

          Note

          Pushing back characters gives you unexpected possibilities to cause the scanner to loop!

          The following example would match a simple Erlang integer or float and return a -token which could be sent to the Erlang parser:

          D = [0-9]
          +token which could be sent to the Erlang parser:

          D = [0-9]
           
          -{D}+ :
          -  {token,{integer,TokenLine,list_to_integer(TokenChars)}}.
          +{D}+ :
          +  {token,{integer,TokenLine,list_to_integer(TokenChars)}}.
           
          -{D}+\.{D}+((E|e)(\+|\-)?{D}+)? :
          -  {token,{float,TokenLine,list_to_float(TokenChars)}}.

          The Erlang code in the Erlang code. section is written into the output file +{D}+\.{D}+((E|e)(\+|\-)?{D}+)? : + {token,{float,TokenLine,list_to_float(TokenChars)}}.

          The Erlang code in the Erlang code. section is written into the output file directly after the module declaration and predefined exports declaration, making it possible to add extra exports, define imports, and other attributes, which are visible in the whole file.

          Regular Expressions

          The regular expressions allowed here is a subset of the set found in egrep and @@ -591,7 +591,7 @@ the token. This is continued until a token has been scanned. Cont is initially [].

          It is not designed to be called directly by an application, but is used through the I/O system where it can typically be called in an -application by:

          io:request(InFile, {get_until,unicode,Prompt,Module,token,[Loc]})
          +application by:

          io:request(InFile, {get_until,unicode,Prompt,Module,token,[Loc]})
             -> TokenRet
          @@ -680,7 +680,7 @@ like Erlang where there is an explicit end token, '.'. If no end token is found then the whole file will be scanned and returned. If an error occurs then all tokens up to and including the next end token will be skipped.

          It is not designed to be called directly by an application, but used through the -I/O system where it can typically be called in an application by:

          io:request(InFile, {get_until,unicode,Prompt,Module,tokens,[Loc]})
          +I/O system where it can typically be called in an application by:

          io:request(InFile, {get_until,unicode,Prompt,Module,tokens,[Loc]})
             -> TokensRet
          /usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub/OEBPS/notes.xhtml differs (HTML document, ASCII text, with very long lines (3348)) --- old//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -17,9 +17,9 @@

          Parsetools Release Notes

          -

          This document describes the changes made to the Parsetools application.

          Parsetools 2.7.1

          Fixed Bugs and Malfunctions

          • The documentation for the token/3 and tokens/3 functions was corrected. The return value when there were too few characters is {more,Cont}.

            Own Id: OTP-19901 Aux Id: PR-10484

          Parsetools 2.7

          Improvements and New Features

          • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

            All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

            -type meter() :: integer().
            --type foot() :: integer().

            Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

            -nominal meter() :: integer().
            --nominal foot() :: integer().

            More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

            Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

            Own Id: OTP-19364 Aux Id: PR-9079

          • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

            Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

          • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

            Own Id: OTP-19575 Aux Id: PR-9670

          Parsetools 2.6

          Improvements and New Features

          • The leex documentation has been updated to use specs for documenting the generated interface.

            Own Id: OTP-18796 Aux Id: PR-7703

          • yecc now wraps the -module attribute with -file to indicate the .yrl source file.

            Own Id: OTP-18912 Aux Id: PR-7963

          • The documentation has been migrated to use Markdown and ExDoc.

            Own Id: OTP-18955 Aux Id: PR-8026

          Parsetools 2.5

          Improvements and New Features

          • Leex has been extended with optional column number support.

            Own Id: OTP-18491 Aux Id: PR-6882

          Parsetools 2.4.1

          Improvements and New Features

          • There is a new configure option, --enable-deterministic-build, which will +

            This document describes the changes made to the Parsetools application.

            Parsetools 2.7.1

            Fixed Bugs and Malfunctions

            • The documentation for the token/3 and tokens/3 functions was corrected. The return value when there were too few characters is {more,Cont}.

              Own Id: OTP-19901 Aux Id: PR-10484

            Parsetools 2.7

            Improvements and New Features

            • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

              All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

              -type meter() :: integer().
              +-type foot() :: integer().

              Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

              -nominal meter() :: integer().
              +-nominal foot() :: integer().

              More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

              Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

              Own Id: OTP-19364 Aux Id: PR-9079

            • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

              Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

            • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

              Own Id: OTP-19575 Aux Id: PR-9670

            Parsetools 2.6

            Improvements and New Features

            • The leex documentation has been updated to use specs for documenting the generated interface.

              Own Id: OTP-18796 Aux Id: PR-7703

            • yecc now wraps the -module attribute with -file to indicate the .yrl source file.

              Own Id: OTP-18912 Aux Id: PR-7963

            • The documentation has been migrated to use Markdown and ExDoc.

              Own Id: OTP-18955 Aux Id: PR-8026

            Parsetools 2.5

            Improvements and New Features

            • Leex has been extended with optional column number support.

              Own Id: OTP-18491 Aux Id: PR-6882

            Parsetools 2.4.1

            Improvements and New Features

            • There is a new configure option, --enable-deterministic-build, which will apply the deterministic compiler option when building Erlang/OTP. The deterministic option has been improved to eliminate more sources of non-determinism in several applications.

              Own Id: OTP-18165 Aux Id: PR-5965

            Parsetools 2.4

            Improvements and New Features

            • In the generated code, yecc will now quote all atoms coming from terminals /usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub/OEBPS/yecc.xhtml differs (HTML document, ASCII text, with very long lines (1506)) --- old//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub/OEBPS/yecc.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/parsetools.epub/OEBPS/yecc.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -44,8 +44,8 @@ distinguished from all the terminal and non-terminal categories of the syntax rules. The Endsymbol can be declared in the grammar file.

              The simplest case is to segment the input string into a list of identifiers (atoms) and use those atoms both as categories and values of the tokens. For -example, the input string aaa bbb 777, X may be scanned (tokenized) as:

              [{aaa, 1}, {bbb, 1}, {777, 1}, {',' , 1}, {'X', 1},
              - {'$end', 1}].

              This assumes that this is the first line of the input text, and that '$end' is +example, the input string aaa bbb 777, X may be scanned (tokenized) as:

              [{aaa, 1}, {bbb, 1}, {777, 1}, {',' , 1}, {'X', 1},
              + {'$end', 1}].

              This assumes that this is the first line of the input text, and that '$end' is the distinguished end_of_input symbol.

              The Erlang scanner in the io module can be used as a starting point when writing a new scanner. Study yeccscan.erl in order to see how a filter can be added on top of io:scan_erl_form/3 to provide a scanner for Yecc that @@ -103,8 +103,8 @@ element -> atom. element -> list.

          This grammar can be used to generate a parser which parses list expressions, such as (), (a), (peter charles), (a (b c) d (())), ... provided that your -scanner tokenizes, for example, the input (peter charles) as follows:

          [{'(', 1} , {atom, 1, peter}, {atom, 1, charles}, {')', 1},
          - {'$end', 1}]

          When a grammar rule is used by the parser to parse (part of) the input string as +scanner tokenizes, for example, the input (peter charles) as follows:

          [{'(', 1} , {atom, 1, peter}, {atom, 1, charles}, {')', 1},
          + {'$end', 1}]

          When a grammar rule is used by the parser to parse (part of) the input string as a grammatical phrase, the associated code is evaluated, and the value of the last expression becomes the value of the parsed phrase. This value may be used by the parser later to build structures that are values of higher phrases of @@ -116,8 +116,8 @@ element -> atom : '$1'. element -> list : '$1'.

          With this code added to the grammar rules, the parser produces the following value (structure) when parsing the input string (a b c).. This still assumes -that this was the first input line that the scanner tokenized:

          {cons, {atom, 1, a}, {cons, {atom, 1, b},
          -                            {cons, {atom, 1, c}, nil}}}

          The associated code contains pseudo variables '$1', '$2', +that this was the first input line that the scanner tokenized:

          {cons, {atom, 1, a}, {cons, {atom, 1, b},
          +                            {cons, {atom, 1, c}, nil}}}

          The associated code contains pseudo variables '$1', '$2', '$3', and so on. 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 @@ -134,12 +134,12 @@ elements -> element elements : {cons, '$1', '$2'}. elements -> '$empty' : nil. element -> atom : '$1'. -element -> list : '$1'.

      Generating a Parser

      To call the parser generator, use the following command:

      yecc:file(Grammarfile).

      An error message from Yecc will be shown if the grammar is not of the LALR type +element -> list : '$1'.

      Generating a Parser

      To call the parser generator, use the following command:

      yecc:file(Grammarfile).

      An error message from Yecc will be shown if the grammar is not of the LALR type (for example too ambiguous). Shift/reduce conflicts are resolved in favor of shifting if there are no operator precedence declarations. Refer to the yacc documentation on the use of operator precedence.

      The output file contains Erlang source code for a parser module with module name equal to the Parserfile parameter. After compilation, the parser can be called -as follows (the module name is assumed to be myparser):

      myparser:parse(myscanner:scan(Inport))

      The call format can be different if a customized prologue file has been included +as follows (the module name is assumed to be myparser):

      myparser:parse(myscanner:scan(Inport))

      The call format can be different if a customized prologue file has been included when generating the parser instead of the default file lib/parsetools/include/yeccpre.hrl.

      With the standard prologue, this call will return either {ok, Result}, where Result is a structure that the Erlang code of the grammar file has built, or @@ -148,15 +148,15 @@ the screen. The user will have to do this either by printing the returned error messages, or by inserting tests and print instructions in the Erlang code associated with the syntax rules of the grammar file.

      It is also possible to make the parser ask for more input tokens when needed if -the following call format is used:

      myparser:parse_and_scan({Function, Args})
      -myparser:parse_and_scan({Mod, Tokenizer, Args})

      The tokenizer Function is either a fun or a tuple {Mod, Tokenizer}. The call +the following call format is used:

      myparser:parse_and_scan({Function, Args})
      +myparser:parse_and_scan({Mod, Tokenizer, Args})

      The tokenizer Function is either a fun or a tuple {Mod, Tokenizer}. The call apply(Function, Args) or apply({Mod, Tokenizer}, Args) is executed whenever a new token is needed. This, for example, makes it possible to parse from a file, token by token.

      The tokenizer used above has to be implemented so as to return one of the -following:

      {ok, Tokens, EndPosition}
      -{eof, EndPosition}
      -{error, Error_description, EndPosition}

      This conforms to the format used by the scanner in the Erlang io library +following:

      {ok, Tokens, EndPosition}
      +{eof, EndPosition}
      +{error, Error_description, EndPosition}

      This conforms to the format used by the scanner in the Erlang io library module.

      If {eof, EndPosition} is returned immediately, the call to parse_and_scan/1 returns {ok, eof}. If {eof, EndPosition} is returned before the parser expects end of input, parse_and_scan/1 will, of course, return an error @@ -200,36 +200,36 @@ Endsymbol '$end'. grammar -> declaration : '$1'. grammar -> rule : '$1'. -declaration -> symbol symbols dot: {'$1', '$2'}. -rule -> head '->' symbols attached_code dot: {rule, ['$1' | '$3'], - '$4'}. +declaration -> symbol symbols dot: {'$1', '$2'}. +rule -> head '->' symbols attached_code dot: {rule, ['$1' | '$3'], + '$4'}. head -> symbol : '$1'. -symbols -> symbol : ['$1']. -symbols -> symbol symbols : ['$1' | '$2']. -attached_code -> ':' tokens : {erlang_code, '$2'}. -attached_code -> '$empty' : {erlang_code, - [{atom, 0, '$undefined'}]}. -tokens -> token : ['$1']. -tokens -> token tokens : ['$1' | '$2']. -symbol -> var : value_of('$1'). -symbol -> atom : value_of('$1'). -symbol -> integer : value_of('$1'). -symbol -> reserved_word : value_of('$1'). +symbols -> symbol : ['$1']. +symbols -> symbol symbols : ['$1' | '$2']. +attached_code -> ':' tokens : {erlang_code, '$2'}. +attached_code -> '$empty' : {erlang_code, + [{atom, 0, '$undefined'}]}. +tokens -> token : ['$1']. +tokens -> token tokens : ['$1' | '$2']. +symbol -> var : value_of('$1'). +symbol -> atom : value_of('$1'). +symbol -> integer : value_of('$1'). +symbol -> reserved_word : value_of('$1'). token -> var : '$1'. token -> atom : '$1'. token -> float : '$1'. token -> integer : '$1'. token -> string : '$1'. token -> char : '$1'. -token -> reserved_symbol : {value_of('$1'), line_of('$1')}. -token -> reserved_word : {value_of('$1'), line_of('$1')}. -token -> '->' : {'->', line_of('$1')}. -token -> ':' : {':', line_of('$1')}. +token -> reserved_symbol : {value_of('$1'), line_of('$1')}. +token -> reserved_word : {value_of('$1'), line_of('$1')}. +token -> '->' : {'->', line_of('$1')}. +token -> ':' : {':', line_of('$1')}. Erlang code. -value_of(Token) -> - element(3, Token). -line_of(Token) -> - element(2, Token).

      Note

      The symbols '->', and ':' have to be treated in a special way, as they are +value_of(Token) -> + element(3, Token). +line_of(Token) -> + element(2, Token).

      Note

      The symbols '->', and ':' have to be treated in a special way, as they are meta symbols of the grammar notation, as well as terminal symbols of the Yecc grammar.

      5. The file erl_parse.yrl in the lib/stdlib/src directory contains the grammar for Erlang.

      Note

      Syntactic tests are used in the code associated with some rules, and an error /usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/yecc.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1506)) --- old//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/yecc.html 2026-08-21 04:00:26.145338518 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/parsetools-2.7.1/doc/html/yecc.html 2026-08-21 04:00:26.145338518 +0000 @@ -115,8 +115,8 @@ distinguished from all the terminal and non-terminal categories of the syntax rules. The Endsymbol can be declared in the grammar file.

      The simplest case is to segment the input string into a list of identifiers (atoms) and use those atoms both as categories and values of the tokens. For -example, the input string aaa bbb 777, X may be scanned (tokenized) as:

      [{aaa, 1}, {bbb, 1}, {777, 1}, {',' , 1}, {'X', 1},
      - {'$end', 1}].

      This assumes that this is the first line of the input text, and that '$end' is +example, the input string aaa bbb 777, X may be scanned (tokenized) as:

      [{aaa, 1}, {bbb, 1}, {777, 1}, {',' , 1}, {'X', 1},
      + {'$end', 1}].

      This assumes that this is the first line of the input text, and that '$end' is the distinguished end_of_input symbol.

      The Erlang scanner in the io module can be used as a starting point when writing a new scanner. Study yeccscan.erl in order to see how a filter can be added on top of io:scan_erl_form/3 to provide a scanner for Yecc that @@ -174,8 +174,8 @@ element -> atom. element -> list.

      This grammar can be used to generate a parser which parses list expressions, such as (), (a), (peter charles), (a (b c) d (())), ... provided that your -scanner tokenizes, for example, the input (peter charles) as follows:

      [{'(', 1} , {atom, 1, peter}, {atom, 1, charles}, {')', 1},
      - {'$end', 1}]

      When a grammar rule is used by the parser to parse (part of) the input string as +scanner tokenizes, for example, the input (peter charles) as follows:

      [{'(', 1} , {atom, 1, peter}, {atom, 1, charles}, {')', 1},
      + {'$end', 1}]

      When a grammar rule is used by the parser to parse (part of) the input string as a grammatical phrase, the associated code is evaluated, and the value of the last expression becomes the value of the parsed phrase. This value may be used by the parser later to build structures that are values of higher phrases of @@ -187,8 +187,8 @@ element -> atom : '$1'. element -> list : '$1'.

    With this code added to the grammar rules, the parser produces the following value (structure) when parsing the input string (a b c).. This still assumes -that this was the first input line that the scanner tokenized:

    {cons, {atom, 1, a}, {cons, {atom, 1, b},
    -                            {cons, {atom, 1, c}, nil}}}

    The associated code contains pseudo variables '$1', '$2', +that this was the first input line that the scanner tokenized:

    {cons, {atom, 1, a}, {cons, {atom, 1, b},
    +                            {cons, {atom, 1, c}, nil}}}

    The associated code contains pseudo variables '$1', '$2', '$3', and so on. 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 @@ -205,12 +205,12 @@ elements -> element elements : {cons, '$1', '$2'}. elements -> '$empty' : nil. element -> atom : '$1'. -element -> list : '$1'.

    Generating a Parser

    To call the parser generator, use the following command:

    yecc:file(Grammarfile).

    An error message from Yecc will be shown if the grammar is not of the LALR type +element -> list : '$1'.

    Generating a Parser

    To call the parser generator, use the following command:

    yecc:file(Grammarfile).

    An error message from Yecc will be shown if the grammar is not of the LALR type (for example too ambiguous). Shift/reduce conflicts are resolved in favor of shifting if there are no operator precedence declarations. Refer to the yacc documentation on the use of operator precedence.

    The output file contains Erlang source code for a parser module with module name equal to the Parserfile parameter. After compilation, the parser can be called -as follows (the module name is assumed to be myparser):

    myparser:parse(myscanner:scan(Inport))

    The call format can be different if a customized prologue file has been included +as follows (the module name is assumed to be myparser):

    myparser:parse(myscanner:scan(Inport))

    The call format can be different if a customized prologue file has been included when generating the parser instead of the default file lib/parsetools/include/yeccpre.hrl.

    With the standard prologue, this call will return either {ok, Result}, where Result is a structure that the Erlang code of the grammar file has built, or @@ -219,15 +219,15 @@ the screen. The user will have to do this either by printing the returned error messages, or by inserting tests and print instructions in the Erlang code associated with the syntax rules of the grammar file.

    It is also possible to make the parser ask for more input tokens when needed if -the following call format is used:

    myparser:parse_and_scan({Function, Args})
    -myparser:parse_and_scan({Mod, Tokenizer, Args})

    The tokenizer Function is either a fun or a tuple {Mod, Tokenizer}. The call +the following call format is used:

    myparser:parse_and_scan({Function, Args})
    +myparser:parse_and_scan({Mod, Tokenizer, Args})

    The tokenizer Function is either a fun or a tuple {Mod, Tokenizer}. The call apply(Function, Args) or apply({Mod, Tokenizer}, Args) is executed whenever a new token is needed. This, for example, makes it possible to parse from a file, token by token.

    The tokenizer used above has to be implemented so as to return one of the -following:

    {ok, Tokens, EndPosition}
    -{eof, EndPosition}
    -{error, Error_description, EndPosition}

    This conforms to the format used by the scanner in the Erlang io library +following:

    {ok, Tokens, EndPosition}
    +{eof, EndPosition}
    +{error, Error_description, EndPosition}

    This conforms to the format used by the scanner in the Erlang io library module.

    If {eof, EndPosition} is returned immediately, the call to parse_and_scan/1 returns {ok, eof}. If {eof, EndPosition} is returned before the parser expects end of input, parse_and_scan/1 will, of course, return an error @@ -271,36 +271,36 @@ Endsymbol '$end'. grammar -> declaration : '$1'. grammar -> rule : '$1'. -declaration -> symbol symbols dot: {'$1', '$2'}. -rule -> head '->' symbols attached_code dot: {rule, ['$1' | '$3'], - '$4'}. +declaration -> symbol symbols dot: {'$1', '$2'}. +rule -> head '->' symbols attached_code dot: {rule, ['$1' | '$3'], + '$4'}. head -> symbol : '$1'. -symbols -> symbol : ['$1']. -symbols -> symbol symbols : ['$1' | '$2']. -attached_code -> ':' tokens : {erlang_code, '$2'}. -attached_code -> '$empty' : {erlang_code, - [{atom, 0, '$undefined'}]}. -tokens -> token : ['$1']. -tokens -> token tokens : ['$1' | '$2']. -symbol -> var : value_of('$1'). -symbol -> atom : value_of('$1'). -symbol -> integer : value_of('$1'). -symbol -> reserved_word : value_of('$1'). +symbols -> symbol : ['$1']. +symbols -> symbol symbols : ['$1' | '$2']. +attached_code -> ':' tokens : {erlang_code, '$2'}. +attached_code -> '$empty' : {erlang_code, + [{atom, 0, '$undefined'}]}. +tokens -> token : ['$1']. +tokens -> token tokens : ['$1' | '$2']. +symbol -> var : value_of('$1'). +symbol -> atom : value_of('$1'). +symbol -> integer : value_of('$1'). +symbol -> reserved_word : value_of('$1'). token -> var : '$1'. token -> atom : '$1'. token -> float : '$1'. token -> integer : '$1'. token -> string : '$1'. token -> char : '$1'. -token -> reserved_symbol : {value_of('$1'), line_of('$1')}. -token -> reserved_word : {value_of('$1'), line_of('$1')}. -token -> '->' : {'->', line_of('$1')}. -token -> ':' : {':', line_of('$1')}. +token -> reserved_symbol : {value_of('$1'), line_of('$1')}. +token -> reserved_word : {value_of('$1'), line_of('$1')}. +token -> '->' : {'->', line_of('$1')}. +token -> ':' : {':', line_of('$1')}. Erlang code. -value_of(Token) -> - element(3, Token). -line_of(Token) -> - element(2, Token).

    Note

    The symbols '->', and ':' have to be treated in a special way, as they are +value_of(Token) -> + element(3, Token). +line_of(Token) -> + element(2, Token).

    Note

    The symbols '->', and ':' have to be treated in a special way, as they are meta symbols of the grammar notation, as well as terminal symbols of the Yecc grammar.

    5. The file erl_parse.yrl in the lib/stdlib/src directory contains the grammar for Erlang.

    Note

    Syntactic tests are used in the code associated with some rules, and an error /usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> public_key - 1.20.3.4 - urn:uuid:8377e206-06f7-2517-b420-a824f9d64b4f + urn:uuid:1fc38d72-2806-10b6-83e6-06d568d56816 en - 2026-08-21T03:49:36Z + 2042-09-22T17:08:35Z /usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub/OEBPS/public_key_records.xhtml differs (HTML document, ASCII text, with very long lines (2697)) --- old//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub/OEBPS/public_key_records.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub/OEBPS/public_key_records.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -21,57 +21,57 @@ used to handle public key infrastructure. The scope is to describe the data types of each component, not the semantics. For information on the semantics, refer to the relevant standards and RFCs linked in the sections below.

    Use the following include directive to get access to the records and constant -macros described in the following sections:

     -include_lib("public_key/include/public_key.hrl").

    Data Types

    Common non-standard Erlang data types used to describe the record fields in the +macros described in the following sections:

     -include_lib("public_key/include/public_key.hrl").

    Data Types

    Common non-standard Erlang data types used to describe the record fields in the following sections and which are not defined in the Public Key -Reference Manual follows here:

    time() = utc_time() | general_time()
    +Reference Manual follows here:

    time() = utc_time() | general_time()
     
    -utc_time()  = {utcTime, "YYMMDDHHMMSSZ"}
    +utc_time()  = {utcTime, "YYMMDDHHMMSSZ"}
     
    -general_time() = {generalTime, "YYYYMMDDHHMMSSZ"}
    +general_time() = {generalTime, "YYYYMMDDHHMMSSZ"}
     
    -general_name() = {rfc822Name, string()} |
    +general_name() = {rfc822Name, string()} |
     
    -                 {dNSName, string()} |
    +                 {dNSName, string()} |
     
    -                 {x400Address, string() |
    +                 {x400Address, string() |
     
    -                 {directoryName, {rdnSequence, [#'AttributeTypeAndValue'{}]}} |
    +                 {directoryName, {rdnSequence, [#'AttributeTypeAndValue'{}]}} |
     
    -                 {ediPartyName, special_string()} |
    +                 {ediPartyName, special_string()} |
     
    -                 {ediPartyName, special_string(), special_string()} |
    +                 {ediPartyName, special_string(), special_string()} |
     
    -                 {uniformResourceIdentifier, string()} |
    +                 {uniformResourceIdentifier, string()} |
     
    -                 {iPAddress, string()} |
    +                 {iPAddress, string()} |
     
    -                 {registeredId, oid()} |
    +                 {registeredId, oid()} |
     
    -                 {otherName, term()}
    +                 {otherName, term()}
     
    -special_string() = {teletexString, string()} |
    +special_string() = {teletexString, string()} |
      
    -                   {printableString, string()} |
    +                   {printableString, string()} |
     
    -                   {universalString, string()} |
    +                   {universalString, string()} |
     
    -                   {utf8String, binary()} |
    +                   {utf8String, binary()} |
     
    -                   {bmpString, string()}
    +                   {bmpString, string()}
     
    -dist_reason() = unused | keyCompromise | cACompromise | affiliationChanged |
    +dist_reason() = unused | keyCompromise | cACompromise | affiliationChanged |
                     cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise
     
    -OID_macro() = ?OID_name()
    +OID_macro() = ?OID_name()
     
    -OID_name() = atom()

    RSA

    Erlang representation of +OID_name() = atom()

    RSA

    Erlang representation of Rivest-Shamir-Adleman cryptosystem (RSA) -keys follows:

    #'RSAPublicKey'{
    +keys follows:

    #'RSAPublicKey'{
        modulus,       % pos_integer()
        publicExponent % pos_integer()
    -  }.
    +  }.
     
    -#'RSAPrivateKey'{
    +#'RSAPrivateKey'{
        version,         % two-prime | multi
        modulus,         % pos_integer()
        publicExponent,  % pos_integer()
    @@ -82,89 +82,89 @@
        exponent2,       % pos_integer()
        coefficient,     % pos_integer()
        otherPrimeInfos  % [#OtherPrimeInfo{}] | asn1_NOVALUE
    -  }.
    +  }.
     
    -#'OtherPrimeInfo'{
    +#'OtherPrimeInfo'{
        prime,           % pos_integer()
        exponent,        % pos_integer()
        coefficient      % pos_integer()
    -  }.
    +  }.
     
    -#'RSASSA-PSS-params'{
    +#'RSASSA-PSS-params'{
        hashAlgorithm,     % #'HashAlgorithm'{}},
        maskGenAlgorithm,  % #'MaskGenAlgorithm'{}},
        saltLength,        % pos_integer(),
        trailerField,      % pos_integer()
    -  }.
    +  }.
     
    -#'HashAlgorithm'{
    +#'HashAlgorithm'{
        algorithm,  % oid()
        parameters  % defaults to asn1_NOVALUE
    -  }.
    +  }.
     
    -#'MaskGenAlgorithm'{
    +#'MaskGenAlgorithm'{
        algorithm,  % oid()
        parameters, % defaults to asn1_NOVALUE
    -  }.

    DSA

    Erlang representation of -Digital Signature Algorithm (DSA) keys

    #'DSAPrivateKey'{
    +  }.

    DSA

    Erlang representation of +Digital Signature Algorithm (DSA) keys

    #'DSAPrivateKey'{
        version,      % pos_integer()
        p,            % pos_integer()
        q,            % pos_integer()
        g,            % pos_integer()
        y,            % pos_integer()
        x             % pos_integer()
    -  }.
    +  }.
     
    -#'Dss-Parms'{
    +#'Dss-Parms'{
        p,         % pos_integer()
        q,         % pos_integer()
        g          % pos_integer()
    -  }.

    ECDSA and EDDSA

    Erlang representation of + }.

    ECDSA and EDDSA

    Erlang representation of Elliptic Curve Digital Signature Algorithm (ECDSA) and Edwards-Curve Digital Signature Algorithm (EDDSA) where parameters in the private key will be -{namedCurve, ?'id-Ed25519' | ?'id-Ed448'}.

    #'ECPrivateKey'{
    +{namedCurve, ?'id-Ed25519' | ?'id-Ed448'}.

    #'ECPrivateKey'{
        version,       % pos_integer() |  ecPrivkeyVer1 (enumeration value, decode returns atom, encode accepts both)
        privateKey,    % binary()
        parameters,    % {ecParameters, #'ECParameters'{}} | - Legacy
                       % {namedCurve, Oid::tuple()} |
                       % {implicitlyCA, 'NULL'}
        publicKey      % bitstring()
    -  }.
    +  }.
     
     %% Legacy no longer defined in current PKIX standard
    -#'ECParameters'{
    +#'ECParameters'{
        version,    % pos_integer() | v1 (enumeration value)
        fieldID,    % #'FieldID'{}
        curve,      % #'Curve'{}
        base,       % binary()
        order,      % pos_integer()
        cofactor    % pos_integer()
    -  }.
    +  }.
     
    -#'Curve'{
    +#'Curve'{
        a,        % binary()
        b,        % binary()
        seed      % bitstring() - optional
    -  }.
    +  }.
     
    -#'FieldID'{
    +#'FieldID'{
        fieldType,    % oid()
        parameters    % Depending on fieldType
    -  }.
    +  }.
     
    -#'ECPoint'{
    +#'ECPoint'{
        point %  binary() - the public key
    -  }.

    PKIX Certificates

    Erlang representation of PKIX certificates derived from ASN.1 specifications see + }.

    PKIX Certificates

    Erlang representation of PKIX certificates derived from ASN.1 specifications see also X509 certificates (RFC 5280), also -referred to as plain type, are as follows:

    #'Certificate'{
    +referred to as plain type, are as follows:

    #'Certificate'{
        tbsCertificate,        % #'TBSCertificate'{}
        signatureAlgorithm,    % #'AlgorithmIdentifier'{}
        signature              % bitstring()
    -  }.
    +  }.
     
    -#'TBSCertificate'{
    +#'TBSCertificate'{
        version,              % v1 | v2 | v3
        serialNumber,         % pos_integer()
    /usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub/OEBPS/public_key.xhtml differs (HTML document, ASCII text, with very long lines (403))
    --- old//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub/OEBPS/public_key.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub/OEBPS/public_key.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -2799,22 +2799,22 @@
     or also by the user when the option policy_set is provided to this
     function. The qualifiers convey information about the valid policy and
     is intended as information to end users.

    Available options:

    • {verify_fun, {fun(), UserState::term()} - The fun must be -defined as:

      fun(OtpCert :: #'OTPCertificate'{},
      -    Event :: {bad_cert, Reason :: bad_cert_reason() | {revoked, atom()}} |
      -             {extension, #'Extension'{}},
      -    UserState :: term()) ->
      -  {valid, UserState :: term()} |
      -  {valid_peer, UserState :: term()} |
      -  {fail, Reason :: term()} |
      -  {unknown, UserState :: term()}.

      or as:

      fun(OtpCert :: #'OTPCertificate'{},
      -    DerCert :: der_encoded(),
      -    Event :: {bad_cert, Reason :: bad_cert_reason() | {revoked, atom()}} |
      -             {extension, #'Extension'{}},
      -    UserState :: term()) ->
      -  {valid, UserState :: term()} |
      -  {valid_peer, UserState :: term()} |
      -  {fail, Reason :: term()} |
      -  {unknown, UserState :: term()}.

      The verify callback can have 3 or 4 arguments in case the DER encoded +defined as:

      fun(OtpCert :: #'OTPCertificate'{},
      +    Event :: {bad_cert, Reason :: bad_cert_reason() | {revoked, atom()}} |
      +             {extension, #'Extension'{}},
      +    UserState :: term()) ->
      +  {valid, UserState :: term()} |
      +  {valid_peer, UserState :: term()} |
      +  {fail, Reason :: term()} |
      +  {unknown, UserState :: term()}.

      or as:

      fun(OtpCert :: #'OTPCertificate'{},
      +    DerCert :: der_encoded(),
      +    Event :: {bad_cert, Reason :: bad_cert_reason() | {revoked, atom()}} |
      +             {extension, #'Extension'{}},
      +    UserState :: term()) ->
      +  {valid, UserState :: term()} |
      +  {valid_peer, UserState :: term()} |
      +  {fail, Reason :: term()} |
      +  {unknown, UserState :: term()}.

      The verify callback can have 3 or 4 arguments in case the DER encoded version is needed by the callback.

      If the verify callback fun returns {fail, Reason}, the verification process is immediately stopped. If the verify callback fun returns {valid, UserState}, the verification process is continued. This can be used @@ -2992,9 +2992,9 @@ about hostname verification. The User's Guide and code examples describes this -function more detailed.

      The option funs are described here:

      • match_fun

        fun(ReferenceId::ReferenceId() | FQDN::string(),
        -    PresentedId::{dNSName,string()} | {uniformResourceIdentifier,string() |
        -                 {iPAddress,list(byte())} | {OtherId::atom()|oid(),term()}})

        This function replaces the default host name matching rules. The fun should +function more detailed.

        The option funs are described here:

        • match_fun

          fun(ReferenceId::ReferenceId() | FQDN::string(),
          +    PresentedId::{dNSName,string()} | {uniformResourceIdentifier,string() |
          +                 {iPAddress,list(byte())} | {OtherId::atom()|oid(),term()}})

          This function replaces the default host name matching rules. The fun should return a boolean to tell if the Reference ID and Presented ID matches or not. The match fun can also return a third value, value, the atom default, if the default matching rules shall apply. This makes it possible to augment the @@ -3189,14 +3189,14 @@

          Performs CRL validation. It is intended to be called from the verify fun of -pkix_path_validation/3 .

          Available options:

          • {update_crl, fun()} - The fun has the following type specification:

             fun(#'DistributionPoint'{}, #'CertificateList'{}) ->
            -        #'CertificateList'{}

            The fun uses the information in the distribution point to access the latest +pkix_path_validation/3 .

            Available options:

            • {update_crl, fun()} - The fun has the following type specification:

               fun(#'DistributionPoint'{}, #'CertificateList'{}) ->
              +        #'CertificateList'{}

              The fun uses the information in the distribution point to access the latest possible version of the CRL. If this fun is not specified, Public Key uses the default implementation:

               fun(_DP, CRL) -> CRL end
            • {issuer_fun, {fun(), UserState::term()}} - The fun has the following type -specification:

              fun(#'DistributionPoint'{}, #'CertificateList'{},
              -    {rdnSequence,[#'AttributeTypeAndValue'{}]}, UserState::term()) ->
              -  {ok, #'OTPCertificate'{}, [der_encoded]}

              The fun returns the root certificate and certificate chain that has signed the -CRL.

               fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain}
            • {undetermined_details, boolean()} - Defaults to false. When revocation +specification:

              fun(#'DistributionPoint'{}, #'CertificateList'{},
              +    {rdnSequence,[#'AttributeTypeAndValue'{}]}, UserState::term()) ->
              +  {ok, #'OTPCertificate'{}, [der_encoded]}

              The fun returns the root certificate and certificate chain that has signed the +CRL.

               fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain}
            • {undetermined_details, boolean()} - Defaults to false. When revocation status cannot be determined, and this option is set to true, details of why no CRLs where accepted are included in the return value.

    @@ -4387,18 +4387,18 @@ generating an ECDSA key. Note this could fail if Erlang/OTP is compiled with a very old cryptolib.

  • {validity, {From::erlang:timestamp(), To::erlang:timestamp()}} - The validity period of the certificate.

  • {extensions, [#'Extension'{}]} - Extensions to include in the -certificate.

    Default extensions included in CA certificates if not otherwise specified are:

    [#'Extension'{extnID = ?'id-ce-keyUsage',
    -              extnValue = [keyCertSign, cRLSign],
    -              critical = false},
    -#'Extension'{extnID = ?'id-ce-basicConstraints',
    -             extnValue = #'BasicConstraints'{cA = true},
    -             critical = true}]

    Default extensions included in the server peer cert if not otherwise specified -are:

    [#'Extension'{extnID = ?'id-ce-keyUsage',
    -              extnValue = [digitalSignature, keyAgreement],
    -              critical = false},
    -#'Extension'{extnID = ?'id-ce-subjectAltName',
    -             extnValue = [{dNSName, Hostname}],
    -             critical = false}]

    Hostname is the result of calling net_adm:localhost() in the Erlang node where +certificate.

    Default extensions included in CA certificates if not otherwise specified are:

    [#'Extension'{extnID = ?'id-ce-keyUsage',
    +              extnValue = [keyCertSign, cRLSign],
    +              critical = false},
    +#'Extension'{extnID = ?'id-ce-basicConstraints',
    +             extnValue = #'BasicConstraints'{cA = true},
    +             critical = true}]

    Default extensions included in the server peer cert if not otherwise specified +are:

    [#'Extension'{extnID = ?'id-ce-keyUsage',
    +              extnValue = [digitalSignature, keyAgreement],
    +              critical = false},
    +#'Extension'{extnID = ?'id-ce-subjectAltName',
    +             extnValue = [{dNSName, Hostname}],
    +             critical = false}]

    Hostname is the result of calling net_adm:localhost() in the Erlang node where this function is called.

  • Note

    Note that the generated certificates and keys does not provide a formally correct PKIX-trust-chain and they cannot be used to achieve real security. This function is provided for testing purposes only.

    /usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub/OEBPS/using_public_key.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1182)) --- old//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub/OEBPS/using_public_key.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.epub/OEBPS/using_public_key.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -28,24 +28,24 @@ -----END <SOMETHING>----- <text>

    A file can contain several BEGIN/END blocks. Text lines between blocks are ignored. Attributes, if present, are ignored except for Proc-Type and -DEK-Info, which are used when DER data is encrypted.

    DSA Private Key

    A DSA private key can look as follows:

    Note

    File handling is not done by the Public Key application.

    1> {ok, PemBin} = file:read_file("dsa.pem").
    -{ok,<<"-----BEGIN DSA PRIVATE KEY-----\nMIIBuw"...>>}

    The following PEM file has only one entry, a private DSA key:

    2>[DSAEntry] =  public_key:pem_decode(PemBin).
    -[{'DSAPrivateKey',<<48,130,1,187,2,1,0,2,129,129,0,183,
    +DEK-Info, which are used when DER data is encrypted.

    DSA Private Key

    A DSA private key can look as follows:

    Note

    File handling is not done by the Public Key application.

    1> {ok, PemBin} = file:read_file("dsa.pem").
    +{ok,<<"-----BEGIN DSA PRIVATE KEY-----\nMIIBuw"...>>}

    The following PEM file has only one entry, a private DSA key:

    2>[DSAEntry] =  public_key:pem_decode(PemBin).
    +[{'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,...>>,
    -                    not_encrypted}]
    3> Key = public_key:pem_entry_decode(DSAEntry).
    -#'DSAPrivateKey'{version = 0,
    +                    162,207,61,246,...>>,
    +                    not_encrypted}]
    3> Key = public_key:pem_entry_decode(DSAEntry).
    +#'DSAPrivateKey'{version = 0,
                      p = 12900045185019966618...6593,
                      q = 1216700114794736143432235288305776850295620488937,
                      g = 10442040227452349332...47213,
                      y = 87256807980030509074...403143,
    -                 x = 510968529856012146351317363807366575075645839654}

    RSA Private Key with Password

    An RSA private key encrypted with a password can look as follows:

    1> {ok, PemBin} = file:read_file("rsa.pem").
    -{ok,<<"Bag Attribute"...>>}

    The following PEM file has only one entry, a private RSA key:

    2>[RSAEntry] = public_key:pem_decode(PemBin).
    -[{'RSAPrivateKey',<<224,108,117,203,152,40,15,77,128,126,
    +                 x = 510968529856012146351317363807366575075645839654}

    RSA Private Key with Password

    An RSA private key encrypted with a password can look as follows:

    1> {ok, PemBin} = file:read_file("rsa.pem").
    +{ok,<<"Bag Attribute"...>>}

    The following PEM file has only one entry, a private RSA key:

    2>[RSAEntry] = public_key:pem_decode(PemBin).
    +[{'RSAPrivateKey',<<224,108,117,203,152,40,15,77,128,126,
                         221,195,154,249,85,208,202,251,109,
    -                    119,120,57,29,89,19,9,...>>,
    -                  {"DES-EDE3-CBC",<<"kÙeø¼pµL">>}}]

    In this following example, the password is "abcd1234":

    3> Key = public_key:pem_entry_decode(RSAEntry, "abcd1234").
    -#'RSAPrivateKey'{version = 'two-prime',
    +                    119,120,57,29,89,19,9,...>>,
    +                  {"DES-EDE3-CBC",<<"kÙeø¼pµL">>}}]

    In this following example, the password is "abcd1234":

    3> Key = public_key:pem_entry_decode(RSAEntry, "abcd1234").
    +#'RSAPrivateKey'{version = 'two-prime',
                      modulus = 1112355156729921663373...2737107,
                      publicExponent = 65537,
                      privateExponent = 58064406231183...2239766033,
    @@ -54,226 +54,226 @@
                      exponent1 = 77928819327425934607...22152984217,
                      exponent2 = 36287623121853605733...20588523793,
                      coefficient = 924840412626098444...41820968343,
    -                 otherPrimeInfos = asn1_NOVALUE}

    X509 Certificates

    The following is an example of X509 certificates:

    1> {ok, PemBin} = file:read_file("cacerts.pem").
    -{ok,<<"-----BEGIN CERTIFICATE-----\nMIIC7jCCAl"...>>}

    The following file includes two certificates:

    2> [CertEntry1, CertEntry2] = public_key:pem_decode(PemBin).
    -[{'Certificate',<<48,130,2,238,48,130,2,87,160,3,2,1,2,2,
    +                 otherPrimeInfos = asn1_NOVALUE}

    X509 Certificates

    The following is an example of X509 certificates:

    1> {ok, PemBin} = file:read_file("cacerts.pem").
    +{ok,<<"-----BEGIN CERTIFICATE-----\nMIIC7jCCAl"...>>}

    The following file includes two certificates:

    2> [CertEntry1, CertEntry2] = public_key:pem_decode(PemBin).
    +[{'Certificate',<<48,130,2,238,48,130,2,87,160,3,2,1,2,2,
                       9,0,230,145,97,214,191,2,120,150,48,13,
    -                  ...>>,
    -                not_encrypted},
    - {'Certificate',<<48,130,3,200,48,130,3,49,160,3,2,1,2,2,1,
    -                  1,48,13,6,9,42,134,72,134,247,...>>,
    -                not_encrypted}]

    Certificates can be decoded as usual:

    2> Cert = public_key:pem_entry_decode(CertEntry1).
    -#'Certificate'{
    +                  ...>>,
    +                not_encrypted},
    + {'Certificate',<<48,130,3,200,48,130,3,49,160,3,2,1,2,2,1,
    +                  1,48,13,6,9,42,134,72,134,247,...>>,
    +                not_encrypted}]

    Certificates can be decoded as usual:

    2> Cert = public_key:pem_entry_decode(CertEntry1).
    +#'Certificate'{
         tbsCertificate =
    -        #'TBSCertificate'{
    +        #'TBSCertificate'{
                 version = v3,serialNumber = 16614168075301976214,
                 signature =
    -                #'AlgorithmIdentifier'{
    -                    algorithm = {1,2,840,113549,1,1,5},
    -                    parameters = <<5,0>>},
    +                #'AlgorithmIdentifier'{
    +                    algorithm = {1,2,840,113549,1,1,5},
    +                    parameters = <<5,0>>},
                 issuer =
    -                {rdnSequence,
    -                    [[#'AttributeTypeAndValue'{
    -                          type = {2,5,4,3},
    -                          value = <<19,8,101,114,108,97,110,103,67,65>>}],
    -                     [#'AttributeTypeAndValue'{
    -                          type = {2,5,4,11},
    -                          value = <<19,10,69,114,108,97,110,103,32,79,84,80>>}],
    -                     [#'AttributeTypeAndValue'{
    -                          type = {2,5,4,10},
    -                          value = <<19,11,69,114,105,99,115,115,111,110,32,65,66>>}],
    -                     [#'AttributeTypeAndValue'{
    -                          type = {2,5,4,7},
    -                          value = <<19,9,83,116,111,99,107,104,111,108,109>>}],
    -                     [#'AttributeTypeAndValue'{
    -                          type = {2,5,4,6},
    -                          value = <<19,2,83,69>>}],
    -                     [#'AttributeTypeAndValue'{
    -                          type = {1,2,840,113549,1,9,1},
    -                          value = <<22,22,112,101,116,101,114,64,101,114,...>>}]]},
    +                {rdnSequence,
    +                    [[#'AttributeTypeAndValue'{
    +                          type = {2,5,4,3},
    +                          value = <<19,8,101,114,108,97,110,103,67,65>>}],
    +                     [#'AttributeTypeAndValue'{
    +                          type = {2,5,4,11},
    +                          value = <<19,10,69,114,108,97,110,103,32,79,84,80>>}],
    +                     [#'AttributeTypeAndValue'{
    +                          type = {2,5,4,10},
    +                          value = <<19,11,69,114,105,99,115,115,111,110,32,65,66>>}],
    +                     [#'AttributeTypeAndValue'{
    +                          type = {2,5,4,7},
    +                          value = <<19,9,83,116,111,99,107,104,111,108,109>>}],
    +                     [#'AttributeTypeAndValue'{
    +                          type = {2,5,4,6},
    +                          value = <<19,2,83,69>>}],
    +                     [#'AttributeTypeAndValue'{
    +                          type = {1,2,840,113549,1,9,1},
    +                          value = <<22,22,112,101,116,101,114,64,101,114,...>>}]]},
                 validity =
    -                #'Validity'{
    -                    notBefore = {utcTime,"080109082929Z"},
    -                    notAfter = {utcTime,"080208082929Z"}},
    +                #'Validity'{
    +                    notBefore = {utcTime,"080109082929Z"},
    +                    notAfter = {utcTime,"080208082929Z"}},
                 subject =
    -                {rdnSequence,
    -                    [[#'AttributeTypeAndValue'{
    -                          type = {2,5,4,3},
    -                          value = <<19,8,101,114,108,97,110,103,67,65>>}],
    -                     [#'AttributeTypeAndValue'{
    -                          type = {2,5,4,11},
    -                          value = <<19,10,69,114,108,97,110,103,32,79,84,80>>}],
    -                     [#'AttributeTypeAndValue'{
    -                          type = {2,5,4,10},
    -                          value = <<19,11,69,114,105,99,115,115,111,110,32,...>>}],
    -                     [#'AttributeTypeAndValue'{
    -                          type = {2,5,4,7},
    -                          value = <<19,9,83,116,111,99,107,104,111,108,...>>}],
    -                     [#'AttributeTypeAndValue'{
    -                          type = {2,5,4,6},
    -                          value = <<19,2,83,69>>}],
    -                     [#'AttributeTypeAndValue'{
    -                          type = {1,2,840,113549,1,9,1},
    -                          value = <<22,22,112,101,116,101,114,64,...>>}]]},
    +                {rdnSequence,
    +                    [[#'AttributeTypeAndValue'{
    +                          type = {2,5,4,3},
    +                          value = <<19,8,101,114,108,97,110,103,67,65>>}],
    +                     [#'AttributeTypeAndValue'{
    +                          type = {2,5,4,11},
    +                          value = <<19,10,69,114,108,97,110,103,32,79,84,80>>}],
    +                     [#'AttributeTypeAndValue'{
    +                          type = {2,5,4,10},
    +                          value = <<19,11,69,114,105,99,115,115,111,110,32,...>>}],
    +                     [#'AttributeTypeAndValue'{
    +                          type = {2,5,4,7},
    +                          value = <<19,9,83,116,111,99,107,104,111,108,...>>}],
    +                     [#'AttributeTypeAndValue'{
    +                          type = {2,5,4,6},
    +                          value = <<19,2,83,69>>}],
    +                     [#'AttributeTypeAndValue'{
    +                          type = {1,2,840,113549,1,9,1},
    +                          value = <<22,22,112,101,116,101,114,64,...>>}]]},
                 subjectPublicKeyInfo =
    -                #'SubjectPublicKeyInfo'{
    +                #'SubjectPublicKeyInfo'{
                         algorithm =
    -                        #'AlgorithmIdentifier'{
    -                            algorithm = {1,2,840,113549,1,1,1},
    -                            parameters = <<5,0>>},
    +                        #'AlgorithmIdentifier'{
    +                            algorithm = {1,2,840,113549,1,1,1},
    +                            parameters = <<5,0>>},
                         subjectPublicKey =
    -                        {0,<<48,129,137,2,129,129,0,203,209,187,77,73,231,90,...>>}},
    +                        {0,<<48,129,137,2,129,129,0,203,209,187,77,73,231,90,...>>}},
                 issuerUniqueID = asn1_NOVALUE,
                 subjectUniqueID = asn1_NOVALUE,
                 extensions =
    -                [#'Extension'{
    -                     extnID = {2,5,29,19},
    +                [#'Extension'{
    +                     extnID = {2,5,29,19},
                          critical = true,
    -                     extnValue = [48,3,1,1,255]},
    -                 #'Extension'{
    -                     extnID = {2,5,29,15},
    +                     extnValue = [48,3,1,1,255]},
    +                 #'Extension'{
    +                     extnID = {2,5,29,15},
                          critical = false,
    -                     extnValue = [3,2,1,6]},
    -                 #'Extension'{
    -                     extnID = {2,5,29,14},
    +                     extnValue = [3,2,1,6]},
    +                 #'Extension'{
    +                     extnID = {2,5,29,14},
                          critical = false,
    -                     extnValue = [4,20,27,217,65,152,6,30,142|...]},
    -                 #'Extension'{
    -                     extnID = {2,5,29,17},
    +                     extnValue = [4,20,27,217,65,152,6,30,142|...]},
    +                 #'Extension'{
    +                     extnID = {2,5,29,17},
                          critical = false,
    /usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
    --- old//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.html	2026-08-21 04:00:26.273339352 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key.html	2026-08-21 04:00:26.273339352 +0000
    @@ -2921,22 +2921,22 @@
     or also by the user when the option policy_set is provided to this
     function. The qualifiers convey information about the valid policy and
     is intended as information to end users.

    Available options:

    • {verify_fun, {fun(), UserState::term()} - The fun must be -defined as:

      fun(OtpCert :: #'OTPCertificate'{},
      -    Event :: {bad_cert, Reason :: bad_cert_reason() | {revoked, atom()}} |
      -             {extension, #'Extension'{}},
      -    UserState :: term()) ->
      -  {valid, UserState :: term()} |
      -  {valid_peer, UserState :: term()} |
      -  {fail, Reason :: term()} |
      -  {unknown, UserState :: term()}.

      or as:

      fun(OtpCert :: #'OTPCertificate'{},
      -    DerCert :: der_encoded(),
      -    Event :: {bad_cert, Reason :: bad_cert_reason() | {revoked, atom()}} |
      -             {extension, #'Extension'{}},
      -    UserState :: term()) ->
      -  {valid, UserState :: term()} |
      -  {valid_peer, UserState :: term()} |
      -  {fail, Reason :: term()} |
      -  {unknown, UserState :: term()}.

      The verify callback can have 3 or 4 arguments in case the DER encoded +defined as:

      fun(OtpCert :: #'OTPCertificate'{},
      +    Event :: {bad_cert, Reason :: bad_cert_reason() | {revoked, atom()}} |
      +             {extension, #'Extension'{}},
      +    UserState :: term()) ->
      +  {valid, UserState :: term()} |
      +  {valid_peer, UserState :: term()} |
      +  {fail, Reason :: term()} |
      +  {unknown, UserState :: term()}.

      or as:

      fun(OtpCert :: #'OTPCertificate'{},
      +    DerCert :: der_encoded(),
      +    Event :: {bad_cert, Reason :: bad_cert_reason() | {revoked, atom()}} |
      +             {extension, #'Extension'{}},
      +    UserState :: term()) ->
      +  {valid, UserState :: term()} |
      +  {valid_peer, UserState :: term()} |
      +  {fail, Reason :: term()} |
      +  {unknown, UserState :: term()}.

      The verify callback can have 3 or 4 arguments in case the DER encoded version is needed by the callback.

      If the verify callback fun returns {fail, Reason}, the verification process is immediately stopped. If the verify callback fun returns {valid, UserState}, the verification process is continued. This can be used @@ -3114,9 +3114,9 @@ about hostname verification. The User's Guide and code examples describes this -function more detailed.

      The option funs are described here:

      • match_fun

        fun(ReferenceId::ReferenceId() | FQDN::string(),
        -    PresentedId::{dNSName,string()} | {uniformResourceIdentifier,string() |
        -                 {iPAddress,list(byte())} | {OtherId::atom()|oid(),term()}})

        This function replaces the default host name matching rules. The fun should +function more detailed.

        The option funs are described here:

        • match_fun

          fun(ReferenceId::ReferenceId() | FQDN::string(),
          +    PresentedId::{dNSName,string()} | {uniformResourceIdentifier,string() |
          +                 {iPAddress,list(byte())} | {OtherId::atom()|oid(),term()}})

          This function replaces the default host name matching rules. The fun should return a boolean to tell if the Reference ID and Presented ID matches or not. The match fun can also return a third value, value, the atom default, if the default matching rules shall apply. This makes it possible to augment the @@ -3316,14 +3316,14 @@

          Performs CRL validation. It is intended to be called from the verify fun of -pkix_path_validation/3 .

          Available options:

          • {update_crl, fun()} - The fun has the following type specification:

             fun(#'DistributionPoint'{}, #'CertificateList'{}) ->
            -        #'CertificateList'{}

            The fun uses the information in the distribution point to access the latest +pkix_path_validation/3 .

            Available options:

            • {update_crl, fun()} - The fun has the following type specification:

               fun(#'DistributionPoint'{}, #'CertificateList'{}) ->
              +        #'CertificateList'{}

              The fun uses the information in the distribution point to access the latest possible version of the CRL. If this fun is not specified, Public Key uses the default implementation:

               fun(_DP, CRL) -> CRL end
            • {issuer_fun, {fun(), UserState::term()}} - The fun has the following type -specification:

              fun(#'DistributionPoint'{}, #'CertificateList'{},
              -    {rdnSequence,[#'AttributeTypeAndValue'{}]}, UserState::term()) ->
              -  {ok, #'OTPCertificate'{}, [der_encoded]}

              The fun returns the root certificate and certificate chain that has signed the -CRL.

               fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain}
            • {undetermined_details, boolean()} - Defaults to false. When revocation +specification:

              fun(#'DistributionPoint'{}, #'CertificateList'{},
              +    {rdnSequence,[#'AttributeTypeAndValue'{}]}, UserState::term()) ->
              +  {ok, #'OTPCertificate'{}, [der_encoded]}

              The fun returns the root certificate and certificate chain that has signed the +CRL.

               fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain}
            • {undetermined_details, boolean()} - Defaults to false. When revocation status cannot be determined, and this option is set to true, details of why no CRLs where accepted are included in the return value.

            @@ -4539,18 +4539,18 @@ generating an ECDSA key. Note this could fail if Erlang/OTP is compiled with a very old cryptolib.

          • {validity, {From::erlang:timestamp(), To::erlang:timestamp()}} - The validity period of the certificate.

          • {extensions, [#'Extension'{}]} - Extensions to include in the -certificate.

            Default extensions included in CA certificates if not otherwise specified are:

            [#'Extension'{extnID = ?'id-ce-keyUsage',
            -              extnValue = [keyCertSign, cRLSign],
            -              critical = false},
            -#'Extension'{extnID = ?'id-ce-basicConstraints',
            -             extnValue = #'BasicConstraints'{cA = true},
            -             critical = true}]

            Default extensions included in the server peer cert if not otherwise specified -are:

            [#'Extension'{extnID = ?'id-ce-keyUsage',
            -              extnValue = [digitalSignature, keyAgreement],
            -              critical = false},
            -#'Extension'{extnID = ?'id-ce-subjectAltName',
            -             extnValue = [{dNSName, Hostname}],
            -             critical = false}]

            Hostname is the result of calling net_adm:localhost() in the Erlang node where +certificate.

            Default extensions included in CA certificates if not otherwise specified are:

            [#'Extension'{extnID = ?'id-ce-keyUsage',
            +              extnValue = [keyCertSign, cRLSign],
            +              critical = false},
            +#'Extension'{extnID = ?'id-ce-basicConstraints',
            +             extnValue = #'BasicConstraints'{cA = true},
            +             critical = true}]

            Default extensions included in the server peer cert if not otherwise specified +are:

            [#'Extension'{extnID = ?'id-ce-keyUsage',
            +              extnValue = [digitalSignature, keyAgreement],
            +              critical = false},
            +#'Extension'{extnID = ?'id-ce-subjectAltName',
            +             extnValue = [{dNSName, Hostname}],
            +             critical = false}]

            Hostname is the result of calling net_adm:localhost() in the Erlang node where this function is called.

          Note

          Note that the generated certificates and keys does not provide a formally correct PKIX-trust-chain and they cannot be used to achieve real security. This function is provided for testing purposes only.

          /usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key_records.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2697)) --- old//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key_records.html 2026-08-21 04:00:26.299339521 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/public_key_records.html 2026-08-21 04:00:26.298339514 +0000 @@ -93,57 +93,57 @@ used to handle public key infrastructure. The scope is to describe the data types of each component, not the semantics. For information on the semantics, refer to the relevant standards and RFCs linked in the sections below.

          Use the following include directive to get access to the records and constant -macros described in the following sections:

           -include_lib("public_key/include/public_key.hrl").

          Data Types

          Common non-standard Erlang data types used to describe the record fields in the +macros described in the following sections:

           -include_lib("public_key/include/public_key.hrl").

          Data Types

          Common non-standard Erlang data types used to describe the record fields in the following sections and which are not defined in the Public Key -Reference Manual follows here:

          time() = utc_time() | general_time()
          +Reference Manual follows here:

          time() = utc_time() | general_time()
           
          -utc_time()  = {utcTime, "YYMMDDHHMMSSZ"}
          +utc_time()  = {utcTime, "YYMMDDHHMMSSZ"}
           
          -general_time() = {generalTime, "YYYYMMDDHHMMSSZ"}
          +general_time() = {generalTime, "YYYYMMDDHHMMSSZ"}
           
          -general_name() = {rfc822Name, string()} |
          +general_name() = {rfc822Name, string()} |
           
          -                 {dNSName, string()} |
          +                 {dNSName, string()} |
           
          -                 {x400Address, string() |
          +                 {x400Address, string() |
           
          -                 {directoryName, {rdnSequence, [#href_anchor"ss">'AttributeTypeAndValue'{}]}} |
          +                 {directoryName, {rdnSequence, [#href_anchor"ss">'AttributeTypeAndValue'{}]}} |
           
          -                 {ediPartyName, special_string()} |
          +                 {ediPartyName, special_string()} |
           
          -                 {ediPartyName, special_string(), special_string()} |
          +                 {ediPartyName, special_string(), special_string()} |
           
          -                 {uniformResourceIdentifier, string()} |
          +                 {uniformResourceIdentifier, string()} |
           
          -                 {iPAddress, string()} |
          +                 {iPAddress, string()} |
           
          -                 {registeredId, oid()} |
          +                 {registeredId, oid()} |
           
          -                 {otherName, term()}
          +                 {otherName, term()}
           
          -special_string() = {teletexString, string()} |
          +special_string() = {teletexString, string()} |
            
          -                   {printableString, string()} |
          +                   {printableString, string()} |
           
          -                   {universalString, string()} |
          +                   {universalString, string()} |
           
          -                   {utf8String, binary()} |
          +                   {utf8String, binary()} |
           
          -                   {bmpString, string()}
          +                   {bmpString, string()}
           
          -dist_reason() = unused | keyCompromise | cACompromise | affiliationChanged |
          +dist_reason() = unused | keyCompromise | cACompromise | affiliationChanged |
                           cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise
           
          -OID_macro() = ?OID_name()
          +OID_macro() = ?OID_name()
           
          -OID_name() = atom()

          RSA

          Erlang representation of +OID_name() = atom()

          RSA

          Erlang representation of Rivest-Shamir-Adleman cryptosystem (RSA) -keys follows:

          #href_anchor"ss">'RSAPublicKey'{
          +keys follows:

          #href_anchor"ss">'RSAPublicKey'{
              modulus,       % pos_integer()
              publicExponent % pos_integer()
          -  }.
          +  }.
           
          -#'RSAPrivateKey'{
          +#'RSAPrivateKey'{
              version,         % two-prime | multi
              modulus,         % pos_integer()
              publicExponent,  % pos_integer()
          @@ -154,89 +154,89 @@
              exponent2,       % pos_integer()
              coefficient,     % pos_integer()
              otherPrimeInfos  % [#OtherPrimeInfo{}] | asn1_NOVALUE
          -  }.
          +  }.
           
          -#'OtherPrimeInfo'{
          +#'OtherPrimeInfo'{
              prime,           % pos_integer()
              exponent,        % pos_integer()
              coefficient      % pos_integer()
          -  }.
          +  }.
           
          -#'RSASSA-PSS-params'{
          +#'RSASSA-PSS-params'{
              hashAlgorithm,     % #'HashAlgorithm'{}},
              maskGenAlgorithm,  % #'MaskGenAlgorithm'{}},
              saltLength,        % pos_integer(),
              trailerField,      % pos_integer()
          -  }.
          +  }.
           
          -#'HashAlgorithm'{
          +#'HashAlgorithm'{
              algorithm,  % oid()
              parameters  % defaults to asn1_NOVALUE
          -  }.
          +  }.
           
          -#'MaskGenAlgorithm'{
          +#'MaskGenAlgorithm'{
              algorithm,  % oid()
              parameters, % defaults to asn1_NOVALUE
          -  }.

          DSA

          Erlang representation of -Digital Signature Algorithm (DSA) keys

          #href_anchor"ss">'DSAPrivateKey'{
          +  }.

          DSA

          Erlang representation of +Digital Signature Algorithm (DSA) keys

          #href_anchor"ss">'DSAPrivateKey'{
              version,      % pos_integer()
              p,            % pos_integer()
              q,            % pos_integer()
              g,            % pos_integer()
              y,            % pos_integer()
              x             % pos_integer()
          -  }.
          +  }.
           
          -#'Dss-Parms'{
          +#'Dss-Parms'{
              p,         % pos_integer()
              q,         % pos_integer()
              g          % pos_integer()
          -  }.

          ECDSA and EDDSA

          Erlang representation of + }.

          ECDSA and EDDSA

          Erlang representation of Elliptic Curve Digital Signature Algorithm (ECDSA) and Edwards-Curve Digital Signature Algorithm (EDDSA) where parameters in the private key will be -{namedCurve, ?'id-Ed25519' | ?'id-Ed448'}.

          #href_anchor"ss">'ECPrivateKey'{
          +{namedCurve, ?'id-Ed25519' | ?'id-Ed448'}.

          #href_anchor"ss">'ECPrivateKey'{
              version,       % pos_integer() |  ecPrivkeyVer1 (enumeration value, decode returns atom, encode accepts both)
              privateKey,    % binary()
              parameters,    % {ecParameters, #'ECParameters'{}} | - Legacy
                             % {namedCurve, Oid::tuple()} |
                             % {implicitlyCA, 'NULL'}
              publicKey      % bitstring()
          -  }.
          +  }.
           
           %% Legacy no longer defined in current PKIX standard
          -#'ECParameters'{
          +#'ECParameters'{
              version,    % pos_integer() | v1 (enumeration value)
              fieldID,    % #'FieldID'{}
              curve,      % #'Curve'{}
              base,       % binary()
              order,      % pos_integer()
              cofactor    % pos_integer()
          -  }.
          +  }.
           
          -#'Curve'{
          +#'Curve'{
              a,        % binary()
              b,        % binary()
              seed      % bitstring() - optional
          -  }.
          +  }.
           
          -#'FieldID'{
          +#'FieldID'{
              fieldType,    % oid()
              parameters    % Depending on fieldType
          -  }.
          +  }.
           
          -#'ECPoint'{
          +#'ECPoint'{
              point %  binary() - the public key
          -  }.

          PKIX Certificates

          Erlang representation of PKIX certificates derived from ASN.1 specifications see + }.

          PKIX Certificates

          Erlang representation of PKIX certificates derived from ASN.1 specifications see also X509 certificates (RFC 5280), also -referred to as plain type, are as follows:

          #href_anchor"ss">'Certificate'{
          +referred to as plain type, are as follows:

          #href_anchor"ss">'Certificate'{
              tbsCertificate,        % #'TBSCertificate'{}
              signatureAlgorithm,    % #'AlgorithmIdentifier'{}
              signature              % bitstring()
          -  }.
          +  }.
           
          -#'TBSCertificate'{
          +#'TBSCertificate'{
              version,              % v1 | v2 | v3
              serialNumber,         % pos_integer()
          /usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/using_public_key.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1189))
          --- old//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/using_public_key.html	2026-08-21 04:00:26.329339716 +0000
          +++ new//usr/share/doc/packages/erlang-doc/lib/public_key-1.20.3.4/doc/html/using_public_key.html	2026-08-21 04:00:26.330339723 +0000
          @@ -100,24 +100,24 @@
               -----END <SOMETHING>-----
               <text>

          A file can contain several BEGIN/END blocks. Text lines between blocks are ignored. Attributes, if present, are ignored except for Proc-Type and -DEK-Info, which are used when DER data is encrypted.

          DSA Private Key

          A DSA private key can look as follows:

          Note

          File handling is not done by the Public Key application.

          1> {ok, PemBin} = file:read_file("dsa.pem").
          -{ok,<<"-----BEGIN DSA PRIVATE KEY-----\nMIIBuw"...>>}

          The following PEM file has only one entry, a private DSA key:

          2>[DSAEntry] =  public_key:pem_decode(PemBin).
          -[{'DSAPrivateKey',<<48,130,1,187,2,1,0,2,129,129,0,183,
          +DEK-Info, which are used when DER data is encrypted.

          DSA Private Key

          A DSA private key can look as follows:

          Note

          File handling is not done by the Public Key application.

          1> {ok, PemBin} = file:read_file("dsa.pem").
          +{ok,<<"-----BEGIN DSA PRIVATE KEY-----\nMIIBuw"...>>}

          The following PEM file has only one entry, a private DSA key:

          2>[DSAEntry] =  public_key:pem_decode(PemBin).
          +[{'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,...>>,
          -                    not_encrypted}]
          3> Key = public_key:pem_entry_decode(DSAEntry).
          -#'DSAPrivateKey'{version = 0,
          +                    162,207,61,246,...>>,
          +                    not_encrypted}]
          3> Key = public_key:pem_entry_decode(DSAEntry).
          +#'DSAPrivateKey'{version = 0,
                            p = 12900045185019966618...6593,
                            q = 1216700114794736143432235288305776850295620488937,
                            g = 10442040227452349332...47213,
                            y = 87256807980030509074...403143,
          -                 x = 510968529856012146351317363807366575075645839654}

          RSA Private Key with Password

          An RSA private key encrypted with a password can look as follows:

          1> {ok, PemBin} = file:read_file("rsa.pem").
          -{ok,<<"Bag Attribute"...>>}

          The following PEM file has only one entry, a private RSA key:

          2>[RSAEntry] = public_key:pem_decode(PemBin).
          -[{'RSAPrivateKey',<<224,108,117,203,152,40,15,77,128,126,
          +                 x = 510968529856012146351317363807366575075645839654}

          RSA Private Key with Password

          An RSA private key encrypted with a password can look as follows:

          1> {ok, PemBin} = file:read_file("rsa.pem").
          +{ok,<<"Bag Attribute"...>>}

          The following PEM file has only one entry, a private RSA key:

          2>[RSAEntry] = public_key:pem_decode(PemBin).
          +[{'RSAPrivateKey',<<224,108,117,203,152,40,15,77,128,126,
                               221,195,154,249,85,208,202,251,109,
          -                    119,120,57,29,89,19,9,...>>,
          -                  {"DES-EDE3-CBC",<<"kÙeø¼pµL">>}}]

          In this following example, the password is "abcd1234":

          3> Key = public_key:pem_entry_decode(RSAEntry, "abcd1234").
          -#'RSAPrivateKey'{version = 'two-prime',
          +                    119,120,57,29,89,19,9,...>>,
          +                  {"DES-EDE3-CBC",<<"kÙeø¼pµL">>}}]

          In this following example, the password is "abcd1234":

          3> Key = public_key:pem_entry_decode(RSAEntry, "abcd1234").
          +#'RSAPrivateKey'{version = 'two-prime',
                            modulus = 1112355156729921663373...2737107,
                            publicExponent = 65537,
                            privateExponent = 58064406231183...2239766033,
          @@ -126,226 +126,226 @@
                            exponent1 = 77928819327425934607...22152984217,
                            exponent2 = 36287623121853605733...20588523793,
                            coefficient = 924840412626098444...41820968343,
          -                 otherPrimeInfos = asn1_NOVALUE}

          X509 Certificates

          The following is an example of X509 certificates:

          1> {ok, PemBin} = file:read_file("cacerts.pem").
          -{ok,<<"-----BEGIN CERTIFICATE-----\nMIIC7jCCAl"...>>}

          The following file includes two certificates:

          2> [CertEntry1, CertEntry2] = public_key:pem_decode(PemBin).
          -[{'Certificate',<<48,130,2,238,48,130,2,87,160,3,2,1,2,2,
          +                 otherPrimeInfos = asn1_NOVALUE}

          X509 Certificates

          The following is an example of X509 certificates:

          1> {ok, PemBin} = file:read_file("cacerts.pem").
          +{ok,<<"-----BEGIN CERTIFICATE-----\nMIIC7jCCAl"...>>}

          The following file includes two certificates:

          2> [CertEntry1, CertEntry2] = public_key:pem_decode(PemBin).
          +[{'Certificate',<<48,130,2,238,48,130,2,87,160,3,2,1,2,2,
                             9,0,230,145,97,214,191,2,120,150,48,13,
          -                  ...>>,
          -                not_encrypted},
          - {'Certificate',<<48,130,3,200,48,130,3,49,160,3,2,1,2,2,1,
          -                  1,48,13,6,9,42,134,72,134,247,...>>,
          -                not_encrypted}]

          Certificates can be decoded as usual:

          2> Cert = public_key:pem_entry_decode(CertEntry1).
          -#'Certificate'{
          +                  ...>>,
          +                not_encrypted},
          + {'Certificate',<<48,130,3,200,48,130,3,49,160,3,2,1,2,2,1,
          +                  1,48,13,6,9,42,134,72,134,247,...>>,
          +                not_encrypted}]

          Certificates can be decoded as usual:

          2> Cert = public_key:pem_entry_decode(CertEntry1).
          +#'Certificate'{
               tbsCertificate =
          -        #'TBSCertificate'{
          +        #'TBSCertificate'{
                       version = v3,serialNumber = 16614168075301976214,
                       signature =
          -                #'AlgorithmIdentifier'{
          -                    algorithm = {1,2,840,113549,1,1,5},
          -                    parameters = <<5,0>>},
          +                #'AlgorithmIdentifier'{
          +                    algorithm = {1,2,840,113549,1,1,5},
          +                    parameters = <<5,0>>},
                       issuer =
          -                {rdnSequence,
          -                    [[#'AttributeTypeAndValue'{
          -                          type = {2,5,4,3},
          -                          value = <<19,8,101,114,108,97,110,103,67,65>>}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,11},
          -                          value = <<19,10,69,114,108,97,110,103,32,79,84,80>>}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,10},
          -                          value = <<19,11,69,114,105,99,115,115,111,110,32,65,66>>}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,7},
          -                          value = <<19,9,83,116,111,99,107,104,111,108,109>>}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,6},
          -                          value = <<19,2,83,69>>}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {1,2,840,113549,1,9,1},
          -                          value = <<22,22,112,101,116,101,114,64,101,114,...>>}]]},
          +                {rdnSequence,
          +                    [[#'AttributeTypeAndValue'{
          +                          type = {2,5,4,3},
          +                          value = <<19,8,101,114,108,97,110,103,67,65>>}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,11},
          +                          value = <<19,10,69,114,108,97,110,103,32,79,84,80>>}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,10},
          +                          value = <<19,11,69,114,105,99,115,115,111,110,32,65,66>>}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,7},
          +                          value = <<19,9,83,116,111,99,107,104,111,108,109>>}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,6},
          +                          value = <<19,2,83,69>>}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {1,2,840,113549,1,9,1},
          +                          value = <<22,22,112,101,116,101,114,64,101,114,...>>}]]},
                       validity =
          -                #'Validity'{
          -                    notBefore = {utcTime,"080109082929Z"},
          -                    notAfter = {utcTime,"080208082929Z"}},
          +                #'Validity'{
          +                    notBefore = {utcTime,"080109082929Z"},
          +                    notAfter = {utcTime,"080208082929Z"}},
                       subject =
          -                {rdnSequence,
          -                    [[#'AttributeTypeAndValue'{
          -                          type = {2,5,4,3},
          -                          value = <<19,8,101,114,108,97,110,103,67,65>>}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,11},
          -                          value = <<19,10,69,114,108,97,110,103,32,79,84,80>>}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,10},
          -                          value = <<19,11,69,114,105,99,115,115,111,110,32,...>>}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,7},
          -                          value = <<19,9,83,116,111,99,107,104,111,108,...>>}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {2,5,4,6},
          -                          value = <<19,2,83,69>>}],
          -                     [#'AttributeTypeAndValue'{
          -                          type = {1,2,840,113549,1,9,1},
          -                          value = <<22,22,112,101,116,101,114,64,...>>}]]},
          +                {rdnSequence,
          +                    [[#'AttributeTypeAndValue'{
          +                          type = {2,5,4,3},
          +                          value = <<19,8,101,114,108,97,110,103,67,65>>}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,11},
          +                          value = <<19,10,69,114,108,97,110,103,32,79,84,80>>}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,10},
          +                          value = <<19,11,69,114,105,99,115,115,111,110,32,...>>}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,7},
          +                          value = <<19,9,83,116,111,99,107,104,111,108,...>>}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {2,5,4,6},
          +                          value = <<19,2,83,69>>}],
          +                     [#'AttributeTypeAndValue'{
          +                          type = {1,2,840,113549,1,9,1},
          +                          value = <<22,22,112,101,116,101,114,64,...>>}]]},
                       subjectPublicKeyInfo =
          -                #'SubjectPublicKeyInfo'{
          +                #'SubjectPublicKeyInfo'{
                               algorithm =
          -                        #'AlgorithmIdentifier'{
          -                            algorithm = {1,2,840,113549,1,1,1},
          -                            parameters = <<5,0>>},
          +                        #'AlgorithmIdentifier'{
          +                            algorithm = {1,2,840,113549,1,1,1},
          +                            parameters = <<5,0>>},
                               subjectPublicKey =
          -                        {0,<<48,129,137,2,129,129,0,203,209,187,77,73,231,90,...>>}},
          +                        {0,<<48,129,137,2,129,129,0,203,209,187,77,73,231,90,...>>}},
                       issuerUniqueID = asn1_NOVALUE,
                       subjectUniqueID = asn1_NOVALUE,
                       extensions =
          -                [#'Extension'{
          -                     extnID = {2,5,29,19},
          +                [#'Extension'{
          +                     extnID = {2,5,29,19},
                                critical = true,
          -                     extnValue = [48,3,1,1,255]},
          -                 #'Extension'{
          -                     extnID = {2,5,29,15},
          +                     extnValue = [48,3,1,1,255]},
          +                 #'Extension'{
          +                     extnID = {2,5,29,15},
                                critical = false,
          -                     extnValue = [3,2,1,6]},
          -                 #'Extension'{
          -                     extnID = {2,5,29,14},
          +                     extnValue = [3,2,1,6]},
          +                 #'Extension'{
          +                     extnID = {2,5,29,14},
                                critical = false,
          -                     extnValue = [4,20,27,217,65,152,6,30,142|...]},
          -                 #'Extension'{
          -                     extnID = {2,5,29,17},
          +                     extnValue = [4,20,27,217,65,152,6,30,142|...]},
          +                 #'Extension'{
          +                     extnID = {2,5,29,17},
                                critical = false,
          /usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text)
          --- old//usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
          +++ new//usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
          @@ -4,10 +4,10 @@
                    version="3.0">
             
               reltool - 1.0.3
          -    urn:uuid:5cb1bab4-f322-c3de-03c4-fd579a5fb896
          +    urn:uuid:88cfe798-ffe4-5129-d90f-df780d1f17c3
               en
           
          -    2026-08-21T03:49:23Z
          +    2042-09-22T17:08:22Z
           
             
             
          /usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool.epub/OEBPS/reltool_examples.xhtml differs (HTML document, ASCII text, with very long lines (1764))
          --- old//usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool.epub/OEBPS/reltool_examples.xhtml	2026-08-05 05:56:49.000000000 +0000
          +++ new//usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool.epub/OEBPS/reltool_examples.xhtml	2026-08-05 05:56:49.000000000 +0000
          @@ -21,482 +21,482 @@
           via the GUI frontend process. When the GUI is started, a server process will
           automatically be started. The GUI process is started with reltool:start/0,
           reltool:start/1 or reltool:start_link/1. The pid of its server can be
          -obtained with reltool:get_server/1

          Erlang/OTP 20 [erts-9.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
          -[hipe] [kernel-poll:false]
          -Eshell V9.0  (abort with ^G)
          +obtained with reltool:get_server/1

          Erlang/OTP 20 [erts-9.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
          +[hipe] [kernel-poll:false]
          +Eshell V9.0  (abort with ^G)
           1>
          -1> {ok, Win} = reltool:start([]).
          -{ok,<0.36.01>}
          -2> {ok, Server} = reltool:get_server(Win).
          -{ok,<0.37.01>}
          -3> reltool:get_config(Server).
          -{ok,{sys,[]}}
          +1> {ok, Win} = reltool:start([]).
          +{ok,<0.36.01>}
          +2> {ok, Server} = reltool:get_server(Win).
          +{ok,<0.37.01>}
          +3> reltool:get_config(Server).
          +{ok,{sys,[]}}
           4>
          -4> {ok, Server2} = reltool:start_server([]).
          -{ok,<0.6535.01>}
          -5> reltool:get_config(Server2).
          -{ok,{sys,[]}}
          -6> reltool:stop(Server2).
          -ok

          Inspecting the configuration

          Erlang/OTP 20 [erts-9.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
          -[hipe] [kernel-poll:false]
          -Eshell V9.0  (abort with ^G)
          +4> {ok, Server2} = reltool:start_server([]).
          +{ok,<0.6535.01>}
          +5> reltool:get_config(Server2).
          +{ok,{sys,[]}}
          +6> reltool:stop(Server2).
          +ok

          Inspecting the configuration

          Erlang/OTP 20 [erts-9.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
          +[hipe] [kernel-poll:false]
          +Eshell V9.0  (abort with ^G)
           1>
          -1> Config = {sys, [{escript, "examples/display_args", [{incl_cond, include}]},
          -		   {app, inets, [{incl_cond, include}]},
          -		   {app, mnesia, [{incl_cond, exclude}]},
          -		   {app, ssl, [{incl_cond, exclude}]},
          -		   {app, runtime_tools, [{incl_cond, exclude}]},
          -		   {app, syntax_tools, [{incl_cond, exclude}]}]}.
          -{sys,[{escript,"examples/display_args",[{incl_cond,include}]},
          -      {app,inets,[{incl_cond,include}]},
          -      {app,mnesia,[{incl_cond,exclude}]},
          -      {app,ssl,[{incl_cond,exclude}]},
          -      {app,runtime_tools,[{incl_cond,exclude}]},
          -      {app,syntax_tools,[{incl_cond,exclude}]}]}
          +1> Config = {sys, [{escript, "examples/display_args", [{incl_cond, include}]},
          +		   {app, inets, [{incl_cond, include}]},
          +		   {app, mnesia, [{incl_cond, exclude}]},
          +		   {app, ssl, [{incl_cond, exclude}]},
          +		   {app, runtime_tools, [{incl_cond, exclude}]},
          +		   {app, syntax_tools, [{incl_cond, exclude}]}]}.
          +{sys,[{escript,"examples/display_args",[{incl_cond,include}]},
          +      {app,inets,[{incl_cond,include}]},
          +      {app,mnesia,[{incl_cond,exclude}]},
          +      {app,ssl,[{incl_cond,exclude}]},
          +      {app,runtime_tools,[{incl_cond,exclude}]},
          +      {app,syntax_tools,[{incl_cond,exclude}]}]}
           2>
          -2> {ok, Server} = reltool:start_server([Config]).
          -{ok,<0.66.0>}
          +2> {ok, Server} = reltool:start_server([Config]).
          +{ok,<0.66.0>}
           3>
          -3> reltool:get_config(Server).
          -{ok,{sys,[{escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          -                   [{incl_cond,include}]},
          -          {app,inets,[{incl_cond,include}]},
          -          {app,mnesia,[{incl_cond,exclude}]},
          -          {app,runtime_tools,[{incl_cond,exclude}]},
          -          {app,ssl,[{incl_cond,exclude}]},
          -          {app,syntax_tools,[{incl_cond,exclude}]}]}}
          +3> reltool:get_config(Server).
          +{ok,{sys,[{escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          +                   [{incl_cond,include}]},
          +          {app,inets,[{incl_cond,include}]},
          +          {app,mnesia,[{incl_cond,exclude}]},
          +          {app,runtime_tools,[{incl_cond,exclude}]},
          +          {app,ssl,[{incl_cond,exclude}]},
          +          {app,syntax_tools,[{incl_cond,exclude}]}]}}
           4>
          -4> reltool:get_config(Server, false, false).
          -{ok,{sys,[{escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          -                   [{incl_cond,include}]},
          -          {app,inets,[{incl_cond,include}]},
          -          {app,mnesia,[{incl_cond,exclude}]},
          -          {app,runtime_tools,[{incl_cond,exclude}]},
          -          {app,ssl,[{incl_cond,exclude}]},
          -          {app,syntax_tools,[{incl_cond,exclude}]}]}}
          +4> reltool:get_config(Server, false, false).
          +{ok,{sys,[{escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          +                   [{incl_cond,include}]},
          +          {app,inets,[{incl_cond,include}]},
          +          {app,mnesia,[{incl_cond,exclude}]},
          +          {app,runtime_tools,[{incl_cond,exclude}]},
          +          {app,ssl,[{incl_cond,exclude}]},
          +          {app,syntax_tools,[{incl_cond,exclude}]}]}}
           5>
          -5> reltool:get_config(Server, true, false).
          -{ok,{sys,[{root_dir,"/usr/local/lib/erlang"},
          -          {lib_dirs,[]},
          -          {escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          -                   [{incl_cond,include}]},
          -          {mod_cond,all},
          -          {incl_cond,derived},
          -          {app,inets,
          -               [{incl_cond,include},{vsn,undefined},{lib_dir,undefined}]},
          -          {app,mnesia,[{incl_cond,exclude}]},
          -          {app,runtime_tools,[{incl_cond,exclude}]},
          -          {app,ssl,[{incl_cond,exclude}]},
          -          {app,syntax_tools,[{incl_cond,exclude}]},
          -          {boot_rel,"start_clean"},
          -          {rel,"start_clean","1.0",[]},
          -          {rel,"start_sasl","1.0",[sasl]},
          -          {emu_name,"beam"},
          -          {relocatable,true},
          -          {profile,development},
          -          {incl_sys_filters,[".*"]},
          -          {excl_sys_filters,[]},
          -          {incl_app_filters,[".*"]},
          -          {excl_app_filters,[]},
          -          {rel_app_type,...},
          -          {...}|...]}}
          +5> reltool:get_config(Server, true, false).
          +{ok,{sys,[{root_dir,"/usr/local/lib/erlang"},
          +          {lib_dirs,[]},
          +          {escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          +                   [{incl_cond,include}]},
          +          {mod_cond,all},
          +          {incl_cond,derived},
          +          {app,inets,
          +               [{incl_cond,include},{vsn,undefined},{lib_dir,undefined}]},
          +          {app,mnesia,[{incl_cond,exclude}]},
          +          {app,runtime_tools,[{incl_cond,exclude}]},
          +          {app,ssl,[{incl_cond,exclude}]},
          +          {app,syntax_tools,[{incl_cond,exclude}]},
          +          {boot_rel,"start_clean"},
          +          {rel,"start_clean","1.0",[]},
          +          {rel,"start_sasl","1.0",[sasl]},
          +          {emu_name,"beam"},
          +          {relocatable,true},
          +          {profile,development},
          +          {incl_sys_filters,[".*"]},
          +          {excl_sys_filters,[]},
          +          {incl_app_filters,[".*"]},
          +          {excl_app_filters,[]},
          +          {rel_app_type,...},
          +          {...}|...]}}
           6>
          -6> reltool:get_config(Server, true, true).
          -{ok,{sys,[{root_dir,"/usr/local/lib/erlang"},
          -          {lib_dirs,[]},
          -          {escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          -                   [{incl_cond,include}]},
          -          {mod_cond,all},
          -          {incl_cond,derived},
          -          {erts,[{app,erts,
          -                      [{vsn,"10.0"},
          -                       {lib_dir,"/usr/local/lib/erlang/lib/erts-10.0"},
          -                       {mod,erl_prim_loader,[]},
          -                       {mod,erl_tracer,[]},
          -                       {mod,erlang,[]},
          -                       {mod,erts_code_purger,[]},
          -                       {mod,erts_dirty_process_signal_handler,[]},
          -                       {mod,erts_internal,[]},
          -                       {mod,erts_literal_area_collector,[]},
          -                       {mod,init,[]},
          -                       {mod,erl_init,...},
          -                       {mod,...},
          -                       {...}|...]}]},
          -          {app,compiler,
          -               [{vsn,"7.0.4"},
          -                {lib_dir,"/usr/local/lib/erlang/lib/compiler-7.0.4"},
          -                {mod,beam_a,[]},
          -                {mod,beam_asm,[]},
          -                {mod,beam_block,[]},
          -                {mod,beam_bs,[]},
          -                {mod,beam_bsm,[]},
          -                {mod,beam_clean,[]},
          -                {mod,beam_dead,[]},
          -                {mod,beam_dict,[]},
          -                {mod,beam_disasm,[]},
          -                {mod,beam_except,[]},
          -                {mod,beam_flatten,...},
          -                {mod,...},
          -                {...}|...]},
          -          {app,crypto,
          -               [{vsn,"3.7.4"},
          -                {lib_dir,"/usr/local/lib/erlang/lib/crypto-3.7.4"},
          -                {mod,crypto,[]},
          -                {mod,crypto_ec_curves,[]}]},
          /usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool_examples.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1904))
          --- old//usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool_examples.html	2026-08-21 04:00:26.434340400 +0000
          +++ new//usr/share/doc/packages/erlang-doc/lib/reltool-1.0.3/doc/html/reltool_examples.html	2026-08-21 04:00:26.434340400 +0000
          @@ -93,482 +93,482 @@
           via the GUI frontend process. When the GUI is started, a server process will
           automatically be started. The GUI process is started with reltool:start/0,
           reltool:start/1 or reltool:start_link/1. The pid of its server can be
          -obtained with reltool:get_server/1

          Erlang/OTP 20 [erts-9.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
          -[hipe] [kernel-poll:false]
          -Eshell V9.0  (abort with ^G)
          +obtained with reltool:get_server/1

          Erlang/OTP 20 [erts-9.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
          +[hipe] [kernel-poll:false]
          +Eshell V9.0  (abort with ^G)
           1>
          -1> {ok, Win} = reltool:start([]).
          -{ok,<0.36.01>}
          -2> {ok, Server} = reltool:get_server(Win).
          -{ok,<0.37.01>}
          -3> reltool:get_config(Server).
          -{ok,{sys,[]}}
          +1> {ok, Win} = reltool:start([]).
          +{ok,<0.36.01>}
          +2> {ok, Server} = reltool:get_server(Win).
          +{ok,<0.37.01>}
          +3> reltool:get_config(Server).
          +{ok,{sys,[]}}
           4>
          -4> {ok, Server2} = reltool:start_server([]).
          -{ok,<0.6535.01>}
          -5> reltool:get_config(Server2).
          -{ok,{sys,[]}}
          -6> reltool:stop(Server2).
          -ok

          Inspecting the configuration

          Erlang/OTP 20 [erts-9.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
          -[hipe] [kernel-poll:false]
          -Eshell V9.0  (abort with ^G)
          +4> {ok, Server2} = reltool:start_server([]).
          +{ok,<0.6535.01>}
          +5> reltool:get_config(Server2).
          +{ok,{sys,[]}}
          +6> reltool:stop(Server2).
          +ok

          Inspecting the configuration

          Erlang/OTP 20 [erts-9.0] [source-c13b302] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10]
          +[hipe] [kernel-poll:false]
          +Eshell V9.0  (abort with ^G)
           1>
          -1> Config = {sys, [{escript, "examples/display_args", [{incl_cond, include}]},
          -		   {app, inets, [{incl_cond, include}]},
          -		   {app, mnesia, [{incl_cond, exclude}]},
          -		   {app, ssl, [{incl_cond, exclude}]},
          -		   {app, runtime_tools, [{incl_cond, exclude}]},
          -		   {app, syntax_tools, [{incl_cond, exclude}]}]}.
          -{sys,[{escript,"examples/display_args",[{incl_cond,include}]},
          -      {app,inets,[{incl_cond,include}]},
          -      {app,mnesia,[{incl_cond,exclude}]},
          -      {app,ssl,[{incl_cond,exclude}]},
          -      {app,runtime_tools,[{incl_cond,exclude}]},
          -      {app,syntax_tools,[{incl_cond,exclude}]}]}
          +1> Config = {sys, [{escript, "examples/display_args", [{incl_cond, include}]},
          +		   {app, inets, [{incl_cond, include}]},
          +		   {app, mnesia, [{incl_cond, exclude}]},
          +		   {app, ssl, [{incl_cond, exclude}]},
          +		   {app, runtime_tools, [{incl_cond, exclude}]},
          +		   {app, syntax_tools, [{incl_cond, exclude}]}]}.
          +{sys,[{escript,"examples/display_args",[{incl_cond,include}]},
          +      {app,inets,[{incl_cond,include}]},
          +      {app,mnesia,[{incl_cond,exclude}]},
          +      {app,ssl,[{incl_cond,exclude}]},
          +      {app,runtime_tools,[{incl_cond,exclude}]},
          +      {app,syntax_tools,[{incl_cond,exclude}]}]}
           2>
          -2> {ok, Server} = reltool:start_server([Config]).
          -{ok,<0.66.0>}
          +2> {ok, Server} = reltool:start_server([Config]).
          +{ok,<0.66.0>}
           3>
          -3> reltool:get_config(Server).
          -{ok,{sys,[{escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          -                   [{incl_cond,include}]},
          -          {app,inets,[{incl_cond,include}]},
          -          {app,mnesia,[{incl_cond,exclude}]},
          -          {app,runtime_tools,[{incl_cond,exclude}]},
          -          {app,ssl,[{incl_cond,exclude}]},
          -          {app,syntax_tools,[{incl_cond,exclude}]}]}}
          +3> reltool:get_config(Server).
          +{ok,{sys,[{escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          +                   [{incl_cond,include}]},
          +          {app,inets,[{incl_cond,include}]},
          +          {app,mnesia,[{incl_cond,exclude}]},
          +          {app,runtime_tools,[{incl_cond,exclude}]},
          +          {app,ssl,[{incl_cond,exclude}]},
          +          {app,syntax_tools,[{incl_cond,exclude}]}]}}
           4>
          -4> reltool:get_config(Server, false, false).
          -{ok,{sys,[{escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          -                   [{incl_cond,include}]},
          -          {app,inets,[{incl_cond,include}]},
          -          {app,mnesia,[{incl_cond,exclude}]},
          -          {app,runtime_tools,[{incl_cond,exclude}]},
          -          {app,ssl,[{incl_cond,exclude}]},
          -          {app,syntax_tools,[{incl_cond,exclude}]}]}}
          +4> reltool:get_config(Server, false, false).
          +{ok,{sys,[{escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          +                   [{incl_cond,include}]},
          +          {app,inets,[{incl_cond,include}]},
          +          {app,mnesia,[{incl_cond,exclude}]},
          +          {app,runtime_tools,[{incl_cond,exclude}]},
          +          {app,ssl,[{incl_cond,exclude}]},
          +          {app,syntax_tools,[{incl_cond,exclude}]}]}}
           5>
          -5> reltool:get_config(Server, true, false).
          -{ok,{sys,[{root_dir,"/usr/local/lib/erlang"},
          -          {lib_dirs,[]},
          -          {escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          -                   [{incl_cond,include}]},
          -          {mod_cond,all},
          -          {incl_cond,derived},
          -          {app,inets,
          -               [{incl_cond,include},{vsn,undefined},{lib_dir,undefined}]},
          -          {app,mnesia,[{incl_cond,exclude}]},
          -          {app,runtime_tools,[{incl_cond,exclude}]},
          -          {app,ssl,[{incl_cond,exclude}]},
          -          {app,syntax_tools,[{incl_cond,exclude}]},
          -          {boot_rel,"start_clean"},
          -          {rel,"start_clean","1.0",[]},
          -          {rel,"start_sasl","1.0",[sasl]},
          -          {emu_name,"beam"},
          -          {relocatable,true},
          -          {profile,development},
          -          {incl_sys_filters,[".*"]},
          -          {excl_sys_filters,[]},
          -          {incl_app_filters,[".*"]},
          -          {excl_app_filters,[]},
          -          {rel_app_type,...},
          -          {...}|...]}}
          +5> reltool:get_config(Server, true, false).
          +{ok,{sys,[{root_dir,"/usr/local/lib/erlang"},
          +          {lib_dirs,[]},
          +          {escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          +                   [{incl_cond,include}]},
          +          {mod_cond,all},
          +          {incl_cond,derived},
          +          {app,inets,
          +               [{incl_cond,include},{vsn,undefined},{lib_dir,undefined}]},
          +          {app,mnesia,[{incl_cond,exclude}]},
          +          {app,runtime_tools,[{incl_cond,exclude}]},
          +          {app,ssl,[{incl_cond,exclude}]},
          +          {app,syntax_tools,[{incl_cond,exclude}]},
          +          {boot_rel,"start_clean"},
          +          {rel,"start_clean","1.0",[]},
          +          {rel,"start_sasl","1.0",[sasl]},
          +          {emu_name,"beam"},
          +          {relocatable,true},
          +          {profile,development},
          +          {incl_sys_filters,[".*"]},
          +          {excl_sys_filters,[]},
          +          {incl_app_filters,[".*"]},
          +          {excl_app_filters,[]},
          +          {rel_app_type,...},
          +          {...}|...]}}
           6>
          -6> reltool:get_config(Server, true, true).
          -{ok,{sys,[{root_dir,"/usr/local/lib/erlang"},
          -          {lib_dirs,[]},
          -          {escript,"/usr/local/lib/erlang/lib/reltool-0.7.3/examples/display_args",
          -                   [{incl_cond,include}]},
          -          {mod_cond,all},
          -          {incl_cond,derived},
          -          {erts,[{app,erts,
          -                      [{vsn,"10.0"},
          -                       {lib_dir,"/usr/local/lib/erlang/lib/erts-10.0"},
          -                       {mod,erl_prim_loader,[]},
          -                       {mod,erl_tracer,[]},
          -                       {mod,erlang,[]},
          -                       {mod,erts_code_purger,[]},
          -                       {mod,erts_dirty_process_signal_handler,[]},
          -                       {mod,erts_internal,[]},
          -                       {mod,erts_literal_area_collector,[]},
          -                       {mod,init,[]},
          -                       {mod,erl_init,...},
          -                       {mod,...},
          -                       {...}|...]}]},
          -          {app,compiler,
          -               [{vsn,"7.0.4"},
          -                {lib_dir,"/usr/local/lib/erlang/lib/compiler-7.0.4"},
          -                {mod,beam_a,[]},
          -                {mod,beam_asm,[]},
          -                {mod,beam_block,[]},
          -                {mod,beam_bs,[]},
          -                {mod,beam_bsm,[]},
          -                {mod,beam_clean,[]},
          -                {mod,beam_dead,[]},
          -                {mod,beam_dict,[]},
          -                {mod,beam_disasm,[]},
          -                {mod,beam_except,[]},
          -                {mod,beam_flatten,...},
          -                {mod,...},
          -                {...}|...]},
          -          {app,crypto,
          -               [{vsn,"3.7.4"},
          -                {lib_dir,"/usr/local/lib/erlang/lib/crypto-3.7.4"},
          -                {mod,crypto,[]},
          -                {mod,crypto_ec_curves,[]}]},
          /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dbg.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
          --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dbg.html	2026-08-21 04:00:26.479340693 +0000
          +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dbg.html	2026-08-21 04:00:26.479340693 +0000
          @@ -1896,40 +1896,40 @@
           as the argument of the function call; it cannot be held in a variable
           which in turn is passed to the function. Furthermore, the parse
           transform module ms_transform must be enabled. The easiest way to
          -enable it is by adding the following line to the source file:

          -include_lib("stdlib/include/ms_transform.hrl").

          Failing to include ms_transform.hrl in the source will result in a runtime +enable it is by adding the following line to the source file:

          -include_lib("stdlib/include/ms_transform.hrl").

          Failing to include ms_transform.hrl in the source will result in a runtime error, not a compile-time error.

          This function can also be invoked directly from the Erlang shell, as shown in the examples that follow.

          The head of the fun must be a single pattern that matches a list. That pattern -will be used to match the arguments for the call:

          Examples:

          1> dbg:fun2ms(fun([_,_]) -> true end).
          -[{[&#href_anchor"p">,'_'],[],[true]}]
          -2> dbg:fun2ms(fun(Args) when length(Args) > 6 -> true end).
          -[{'$1',[{'>',{length,'$1'},6}],[true]}]

          The first match specification matches when a function having two +will be used to match the arguments for the call:

          Examples:

          1> dbg:fun2ms(fun([_,_]) -> true end).
          +[{[&#href_anchor"p">,'_'],[],[true]}]
          +2> dbg:fun2ms(fun(Args) when length(Args) > 6 -> true end).
          +[{'$1',[{'>',{length,'$1'},6}],[true]}]

          The first match specification matches when a function having two arguments is called. The second matches when a function with more than -6 arguments is called.

          Examples:

          1> dbg:fun2ms(fun(42) -> true end).
          +6 arguments is called.

          Examples:

          1> dbg:fun2ms(fun(42) -> true end).
           Error: dbg:fun2ms requires fun with single variable or list parameter
          -{error,transform_error}
          -2> dbg:fun2ms(fun([<<H,T/binary>>]) -> true end).
          +{error,transform_error}
          +2> dbg:fun2ms(fun([<<H,T/binary>>]) -> true end).
           Error: fun head contains bit syntax matching of variable 'H', which cannot be translated into match_spec
          -{error,transform_error}

          The preceding two examples show what happens when a fun cannot be +{error,transform_error}

          The preceding two examples show what happens when a fun cannot be translated into a match specification. In the first example, the fun head connot possibly match a list. In the second example, an attempt is made to take apart a binary using the bit syntax, which is currently not -supported in match specifications.

          However, note that literal binaries can be matched:

          1> dbg:fun2ms(fun([<<"abc">>]) -> true end).
          -[{[<<"abc">>],[],[true]}]

          Match specifications support a large subset of the +supported in match specifications.

          However, note that literal binaries can be matched:

          1> dbg:fun2ms(fun([<<"abc">>]) -> true end).
          +[{[<<"abc">>],[],[true]}]

          Match specifications support a large subset of the guard expressions supported -by Erlang, but not all. For example, updating a map is currently not supported:

          1> dbg:fun2ms(fun([M]) when map_size(M#{a => b}) > 2 -> true end).
          -Error: the language element map (in guard) cannot be translated into match_spec
          -{error,transform_error}

          However, creating a map in a guard is allowed:

          1> dbg:fun2ms(fun([M]) when map_size(#{a => b}) > 2 -> true end).
          -[{['$1'],[{'>',{map_size,#{a => b}},2}],[true]}]

          Variables from the environment can be imported, so this works:

          1> X = 3.
          +by Erlang, but not all. For example, updating a map is currently not supported:

          1> dbg:fun2ms(fun([M]) when map_size(M#{a => b}) > 2 -> true end).
          +Error: the language element map (in guard) cannot be translated into match_spec
          +{error,transform_error}

          However, creating a map in a guard is allowed:

          1> dbg:fun2ms(fun([M]) when map_size(#{a => b}) > 2 -> true end).
          +[{['$1'],[{'>',{map_size,#{a => b}},2}],[true]}]

          Variables from the environment can be imported, so this works:

          1> X = 3.
           3
          -2> dbg:fun2ms(fun([M,N]) when N > X  -> return_trace() end).
          -[{['$1','$2'],[{'>','$2',{const,3}}],[{return_trace}]}]

          The imported variables will be replaced by const expressions, which +2> dbg:fun2ms(fun([M,N]) when N > X -> return_trace() end). +[{['$1','$2'],[{'>','$2',{const,3}}],[{return_trace}]}]

          The imported variables will be replaced by const expressions, which is consistent with the static scoping for Erlang funs.

          In the body of the fun, only guard expressions and calls to the special functions for tracing -are allowed.

          Examples:

          1> dbg:fun2ms(fun([A]) when is_atom(A) -> return_trace() end).
          -[{['$1'],[{is_atom,'$1'}],[{return_trace}]}]
          -2> dbg:fun2ms(fun(_) -> erlang:garbage_collect() end).
          -Error: fun containing the remote function call 'erlang:garbage_collect/0' (called in body) cannot be translated into match_spec
          -{error,transform_error}

          Warning

          If the parse transform is not applied to a module which calls dbg:fun2ms/1, +are allowed.

          Examples:

          1> dbg:fun2ms(fun([A]) when is_atom(A) -> return_trace() end).
          +[{['$1'],[{is_atom,'$1'}],[{return_trace}]}]
          +2> dbg:fun2ms(fun(_) -> erlang:garbage_collect() end).
          +Error: fun containing the remote function call 'erlang:garbage_collect/0' (called in body) cannot be translated into match_spec
          +{error,transform_error}

          Warning

          If the parse transform is not applied to a module which calls dbg:fun2ms/1, the call will fail in runtime with a badarg exception.

          More information is available in the documentation for module ms_transform in STDLIB.

          @@ -2137,16 +2137,16 @@ names, parameters, return values, and exceptions raised from functions

        • caller_trace, c - sets a trace that displays function names, parameters, and information about which function called it

        • caller_exception_trace, cx - combines exception_trace and -caller_trace

        Here is an example that shows how to use a built-in match specification:

        1> dbg:tracer().
        -{ok,<0.90.0>}
        -2> dbg:tp(lists, seq, 2, cx).
        -{ok,[{matched,nonode@nohost,1},{saved,cx}]}
        -3> dbg:p(self(), call).
        -{ok,[{matched,nonode@nohost,1}]}
        -4> lists:seq(1, 5).
        -(<0.88.0>) call lists:seq(1,5) ({erl_eval,do_apply,7,{"erl_eval.erl",904}})
        -[1,2,3,4,5]
        -(<0.88.0>) returned from lists:seq/2 -> [1,2,3,4,5]
        +caller_trace

      Here is an example that shows how to use a built-in match specification:

      1> dbg:tracer().
      +{ok,<0.90.0>}
      +2> dbg:tp(lists, seq, 2, cx).
      +{ok,[{matched,nonode@nohost,1},{saved,cx}]}
      +3> dbg:p(self(), call).
      +{ok,[{matched,nonode@nohost,1}]}
      +4> lists:seq(1, 5).
      +(<0.88.0>) call lists:seq(1,5) ({erl_eval,do_apply,7,{"erl_eval.erl",904}})
      +[1,2,3,4,5]
      +(<0.88.0>) returned from lists:seq/2 -> [1,2,3,4,5]
      @@ -2344,37 +2344,37 @@ is provided.

      Any dbg function that is called with in the provided fun will use the session/0 provided instead of the default dbg session. This means that the tracing will be isolated -from other tracing users on the system.

      The function returns the term that the fun returns.

      Example:

      1> S = dbg:session_create(my_session).
      +from other tracing users on the system.

      The function returns the term that the fun returns.

      Example:

      1> S = dbg:session_create(my_session).
       <0.91.0>
      -2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(all,c), dbg:tp(lists,seq,x) end).
      -{ok,[{matched,nonode@nohost,2},{saved,x}]}
      -3> lists:seq(1, 10).
      -(<0.89.0>) call lists:seq(1,10)
      -(<0.89.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10]
      -[1,2,3,4,5,6,7,8,9,10]
      -4> dbg:session_destroy(S).
      +2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(all,c), dbg:tp(lists,seq,x) end).
      +{ok,[{matched,nonode@nohost,2},{saved,x}]}
      +3> lists:seq(1, 10).
      +(<0.89.0>) call lists:seq(1,10)
      +(<0.89.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10]
      +[1,2,3,4,5,6,7,8,9,10]
      +4> dbg:session_destroy(S).
       ok

      The state of the session/0 is preserved in between session/2 calls, so -you can call session/2 multiple when debugging you application.

      Example:

      1> S = dbg:session_create(my_session).
      +you can call session/2 multiple when debugging you application.

      Example:

      1> S = dbg:session_create(my_session).
       <0.91.0>
       %% Setup the initial traces
      -2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(self(),c), dbg:tp(lists,seq,x) end).
      -{ok,[{matched,nonode@nohost,2},{saved,x}]}
      -3> lists:seq(1, 3).
      -(<0.89.0>) call lists:seq(1,3)
      -(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
      -[1,2,3]
      +2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(self(),c), dbg:tp(lists,seq,x) end).
      +{ok,[{matched,nonode@nohost,2},{saved,x}]}
      +3> lists:seq(1, 3).
      +(<0.89.0>) call lists:seq(1,3)
      +(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
      +[1,2,3]
       %% Add an additional trace pattern
      -4> dbg:session(S, fun() -> dbg:tpl(lists,seq_loop,x) end).
      +4> dbg:session(S, fun() -> dbg:tpl(lists,seq_loop,x) end).
       ok
      -5> lists:seq(1, 3).
      -(<0.89.0>) call lists:seq(1,3)
      -(<0.89.0>) call lists:seq_loop(3,3,[])
      -(<0.89.0>) call lists:seq_loop(1,1,[2,3])
      -(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
      -(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
      -(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
      -[1,2,3]
      -6> dbg:session_destroy(S).
      +5> lists:seq(1, 3).
      +(<0.89.0>) call lists:seq(1,3)
      +(<0.89.0>) call lists:seq_loop(3,3,[])
      +(<0.89.0>) call lists:seq_loop(1,1,[2,3])
      +(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
      +(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
      +(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
      +[1,2,3]
      +6> dbg:session_destroy(S).
       ok

      Note

      The session functionality is experimental in Erlang/OTP 27 and may change in future releases without notice.

      @@ -2548,11 +2548,11 @@ and will stand as an "alias" for the given expression.

      If the match specification is invalid, an {error, Errors} tuple is returned. Errors is as a list of tuples {error, string()}, where the string is a textual explanation of the compilation error. For -example:

      1> dbg:tp({dbg,ltp,0},[{[],[],[{message, two, arguments}, {noexist}]}]).
      -{error,
      - [{error,"Special form 'message' called with wrong number of
      -          arguments in {message,two,arguments}."},
      -  {error,"Function noexist/1 does_not_exist."}]}
      +example:

      1> dbg:tp({dbg,ltp,0},[{[],[],[{message, two, arguments}, {noexist}]}]).
      +{error,
      + [{error,"Special form 'message' called with wrong number of
      +          arguments in {message,two,arguments}."},
      +  {error,"Function noexist/1 does_not_exist."}]}
      @@ -2803,17 +2803,17 @@ host Hostname, from where it reads trace messages until the TCP/IP connection is closed. If no Hostname is specified, the local host is assumed.

      As an example, one can let trace messages be sent over the network to another Erlang node (preferably not distributed), where the formatting occurs.

      On the node stack there exists an Erlang node ant@stack. In the -shell, type the following:

      ant@stack> dbg:tracer(port, dbg:trace_port(ip, 4711)).
      +shell, type the following:

      ant@stack> dbg:tracer(port, dbg:trace_port(ip, 4711)).
       <0.17.0>
      -ant@stack> dbg:p(self(), send).
      -{ok,1}

      All trace messages are now sent to the trace port driver, which in turn listens +ant@stack> dbg:p(self(), send). +{ok,1}

      All trace messages are now sent to the trace port driver, which in turn listens for connections on the TCP/IP port 4711. If we want to see the messages on -another node, preferably on another host, we do like this:

      1> dbg:trace_client(ip, {"stack", 4711}).
      +another node, preferably on another host, we do like this:

      1> dbg:trace_client(ip, {"stack", 4711}).
       <0.42.0>

      If we now send a message from the shell on the node ant@stack, where all sends -from the shell are traced:

      ant@stack> self() ! hello.
      +from the shell are traced:

      ant@stack> self() ! hello.
       hello

      The following will appear at the console on the node that started the trace -client:

      (<0.23.0>) <0.23.0> ! hello
      -(<0.23.0>) <0.22.0> ! {shell_rep,<0.23.0>,{value,hello,[],[]}}

      The last line is generated due to internal message passing in the Erlang shell. +client:

      (<0.23.0>) <0.23.0> ! hello
      +(<0.23.0>) <0.22.0> ! {shell_rep,<0.23.0>,{value,hello,[],[]}}

      The last line is generated due to internal message passing in the Erlang shell. The pids will vary.

      @@ -2897,7 +2897,7 @@ /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dbg_guide.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1860)) --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dbg_guide.html 2026-08-21 04:00:26.514340920 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dbg_guide.html 2026-08-21 04:00:26.515340927 +0000 @@ -92,22 +92,22 @@

      The dbg module in Erlang provides a text-based interface for tracing function calls, processes, ports, and messages. It simplifies the use of the underlying trace:process/4, trace:port/4, and trace:function/4 BIFs (Built-In Functions). This guide will walk you through the basics of using dbg for your Erlang applications.

      This facility is useful for both quick debugging sessions in the shell and for more structured system testing, especially where other tools might have too much performance impact.

      Quick Start

      To trace a call to a function with minimal fuss, call dbg:c(Module, Name, Arguments). It starts a temporary trace receiver, enables all trace flags, and calls the designated function from a temporary process. For example, here is how to trace a call -to application:which_applications/0:

      1> dbg:c(application, which_applications, []).
      -(<0.92.0>) <0.45.0> ! {'$gen_call',{<0.92.0>,
      -                                    [alias|
      -                                     #Ref<0.0.11779.270031856.1478295555.230456>]},
      -                                   which_applications} (Timestamp: {1710,
      +to application:which_applications/0:

      1> dbg:c(application, which_applications, []).
      +(<0.92.0>) <0.45.0> ! {'$gen_call',{<0.92.0>,
      +                                    [alias|
      +                                     #Ref<0.0.11779.270031856.1478295555.230456>]},
      +                                   which_applications} (Timestamp: {1710,
                                                                           847802,
      -                                                                    479222})
      -(<0.92.0>) out {gen,do_call,4} (Timestamp: {1710,847802,479231})
      -(<0.92.0>) in {gen,do_call,4} (Timestamp: {1710,847802,479271})
      -(<0.92.0>) << {[alias|#Ref<0.0.11779.270031856.1478295555.230456>],
      -               [{stdlib,"ERTS  CXC 138 10","5.2.1"},
      -                {kernel,"ERTS  CXC 138 10","9.2.2"}]} (Timestamp: {1710,
      +                                                                    479222})
      +(<0.92.0>) out {gen,do_call,4} (Timestamp: {1710,847802,479231})
      +(<0.92.0>) in {gen,do_call,4} (Timestamp: {1710,847802,479271})
      +(<0.92.0>) << {[alias|#Ref<0.0.11779.270031856.1478295555.230456>],
      +               [{stdlib,"ERTS  CXC 138 10","5.2.1"},
      +                {kernel,"ERTS  CXC 138 10","9.2.2"}]} (Timestamp: {1710,
                                                                          847802,
      -                                                                   479274})
      -[{stdlib,"ERTS  CXC 138 10","5.2.1"},
      - {kernel,"ERTS  CXC 138 10","9.2.2"}]

      In this example, four trace events are generated:

      • A send event (!) for the sending of a request from the current process + 479274}) +[{stdlib,"ERTS CXC 138 10","5.2.1"}, + {kernel,"ERTS CXC 138 10","9.2.2"}]

      In this example, four trace events are generated:

      • A send event (!) for the sending of a request from the current process to the application_controller process.
      • A schedule-out event (out) when the current process schedules out while waiting in a receive for the reply to arrive.
      • A schedule-in event (in) when the current process is scheduled in when reply has arrived.
      • A receive event (<<) when the current process retrieves the reply from @@ -116,8 +116,8 @@ tracer and set the trace flags of your choice on the processes you want to trace. This is useful, when there is a complex system of processes, ports or nodes interacting where dbg:c/3 is to blunt.

        Starting a Tracer (dbg:tracer/0,2)

        First, you need to start a tracer process that will receive and display trace -messages.

        1> dbg:tracer().  % Start the default trace message receiver
        -{ok,<0.90.0>}     % <0.90.0> is the PID of the tracer process

        This starts a server on the local node that will be the recipient of all trace +messages.

        1> dbg:tracer().  % Start the default trace message receiver
        +{ok,<0.90.0>}     % <0.90.0> is the PID of the tracer process

        This starts a server on the local node that will be the recipient of all trace messages. It uses a default handler that prints formatted trace messages to the Erlang shell.

        If you need a custom tracer other than the default, you can create a tracer using dbg:tracer(Type, Data):

        • Type = process: Data is {HandlerFun, InitialState}. HandlerFun is @@ -148,18 +148,18 @@ case of a single pid exactly 1). The specification of matched processes is {matched, Node, N}. If the remote processor call (using rpc) to a remote node fails, the rpc error message is returned as the fourth element in the -tuple and the number of matched processes is 0.

          Example: Trace messages and process events for a specific process

          1> Pid = spawn(fun() -> receive {From,Msg} -> From ! Msg end end).
          +tuple and the number of matched processes is 0.

          Example: Trace messages and process events for a specific process

          1> Pid = spawn(fun() -> receive {From,Msg} -> From ! Msg end end).
           <0.90.0>
          -2> dbg:tracer().
          -{ok,<0.92.0>}
          -3> dbg:p(Pid, [m,procs]). % Trace messages and process events for Pid
          -{ok,[{matched,nonode@nohost,1}]}
          -4> Pid ! {self(),hello}.
          -(<0.90.0>) << {<0.88.0>,hello} % Received by Pid
          -{<0.88.0>,hello}
          -(<0.90.0>) <0.88.0> ! hello    % Sent by Pid
          -(<0.90.0>) exit normal         % Process event: Pid exited
          -5> flush().
          +2> dbg:tracer().
          +{ok,<0.92.0>}
          +3> dbg:p(Pid, [m,procs]). % Trace messages and process events for Pid
          +{ok,[{matched,nonode@nohost,1}]}
          +4> Pid ! {self(),hello}.
          +(<0.90.0>) << {<0.88.0>,hello} % Received by Pid
          +{<0.88.0>,hello}
          +(<0.90.0>) <0.88.0> ! hello    % Sent by Pid
          +(<0.90.0>) exit normal         % Process event: Pid exited
          +5> flush().
           Shell got hello
           ok

          Tracing Function Calls (dbg:tp/2,3,4, dbg:tpl/2,3,4)

          To trace function calls, you need to:

          1. Enable the c/call flag for the process(es) that will make the calls (using dbg:p/2).
          2. Set a trace pattern for the function(s) you want to trace using dbg:tp/2 @@ -174,16 +174,16 @@ values, and exceptions. [{'_',[],[{exception_trace}]}]
          3. c or caller_trace: Shows function names, parameters, and caller information. [{'_',[],[{message,{caller_line}}]}]
          4. cx or caller_exception_trace: Combines x and c. -[{'_',[],[{exception_trace},{message,{caller_line}}]}]

      Example using built-in aliases:

      1> dbg:tracer().
      -{ok,<0.90.0>}
      -2> dbg:p(all, c). % Short for dbg:p(all, call)
      -{ok,[{matched,nonode@nohost,49}]}
      -3> dbg:tp(lists, seq, cx). % cx: call and exception tracing with caller info
      -{ok,[{matched,nonode@nohost,2},{saved,cx}]}
      -4> lists:seq(1, 3).
      -(<0.88.0>) call lists:seq(1,3) ({erl_eval,do_apply,7,{"erl_eval.erl",904}})
      -[1,2,3]
      -(<0.88.0>) returned from lists:seq/2 -> [1,2,3]

      Note that the caller info is the function that called lists:seq with file and +[{'_',[],[{exception_trace},{message,{caller_line}}]}]

    Example using built-in aliases:

    1> dbg:tracer().
    +{ok,<0.90.0>}
    +2> dbg:p(all, c). % Short for dbg:p(all, call)
    +{ok,[{matched,nonode@nohost,49}]}
    +3> dbg:tp(lists, seq, cx). % cx: call and exception tracing with caller info
    +{ok,[{matched,nonode@nohost,2},{saved,cx}]}
    +4> lists:seq(1, 3).
    +(<0.88.0>) call lists:seq(1,3) ({erl_eval,do_apply,7,{"erl_eval.erl",904}})
    +[1,2,3]
    +(<0.88.0>) returned from lists:seq/2 -> [1,2,3]

    Note that the caller info is the function that called lists:seq with file and line number.

    Tracing Message Events (dbg:tpe/2)

    By default, if send or receive tracing is enabled for a process, all such events are traced. dbg:tpe(Event, MatchSpec) allows you to filter these events.

    • Event: send or 'receive'.
    • MatchSpec: A match specifications.
      • For send: Matches on [Receiver, Msg].
      • For 'receive': Matches on [Node, Sender, Msg].

    Managing Trace Patterns

    You can display, remove, save and load trace pattern matchspecifications, if @@ -207,10 +207,10 @@ enable it is by adding the following line to the source file: -include_lib("stdlib/include/ms_transform.hrl"). In the shell its already enabled.

    The head of the fun must be a single pattern that matches a list. That pattern -will be used to match the arguments for the call:

    1> dbg:fun2ms(fun([_,_]) -> true end). % Matches a function with two arguments
    -[{[&#href_anchor"p">,'_'],[],[true]}]
    -2> dbg:fun2ms(fun([A]) when is_atom(A) -> return_trace() end).
    -[{['$1'],[{is_atom,'$1'}],[{return_trace}]}]

    The first match specification matches when a function having two +will be used to match the arguments for the call:

    1> dbg:fun2ms(fun([_,_]) -> true end). % Matches a function with two arguments
    +[{[&#href_anchor"p">,'_'],[],[true]}]
    +2> dbg:fun2ms(fun([A]) when is_atom(A) -> return_trace() end).
    +[{['$1'],[{is_atom,'$1'}],[{return_trace}]}]

    The first match specification matches when a function having two arguments is called. The second matches when a function, taking one atom as an argument, is called.

    Trace Sessions

    To avoid interference between different tracing activities, you can create isolated dbg sessions.

    First you create a session with dbg:session_create(Name) @@ -219,37 +219,37 @@ This function runs dbg commands within Fun using the specified session.

    Any dbg function that is called with in the provided fun will use the session/0 provided instead of the default dbg session. This means that the tracing will be isolated -from other tracing users on the system.

    When you no longer need the session, use dbg:session_destroy(Session).

    Example:

    1> S = dbg:session_create(my_session).
    +from other tracing users on the system.

    When you no longer need the session, use dbg:session_destroy(Session).

    Example:

    1> S = dbg:session_create(my_session).
     <0.91.0>
    -2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(all,c), dbg:tp(lists,seq,x) end).
    -{ok,[{matched,nonode@nohost,2},{saved,x}]}
    -3> lists:seq(1, 10).
    -(<0.89.0>) call lists:seq(1,10)
    -(<0.89.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10]
    -[1,2,3,4,5,6,7,8,9,10]
    -4> dbg:session_destroy(S).
    +2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(all,c), dbg:tp(lists,seq,x) end).
    +{ok,[{matched,nonode@nohost,2},{saved,x}]}
    +3> lists:seq(1, 10).
    +(<0.89.0>) call lists:seq(1,10)
    +(<0.89.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10]
    +[1,2,3,4,5,6,7,8,9,10]
    +4> dbg:session_destroy(S).
     ok

    The state of the session/0 is preserved in between dbg:session/2 calls, so -you can call dbg:session/2 multiple times when debugging you application.

    Example:

    1> S = dbg:session_create(my_session).
    +you can call dbg:session/2 multiple times when debugging you application.

    Example:

    1> S = dbg:session_create(my_session).
     <0.91.0>
     %% Setup the initial traces
    -2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(self(),c), dbg:tp(lists,seq,x) end).
    -{ok,[{matched,nonode@nohost,2},{saved,x}]}
    -3> lists:seq(1, 3).
    -(<0.89.0>) call lists:seq(1,3)
    -(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
    -[1,2,3]
    +2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(self(),c), dbg:tp(lists,seq,x) end).
    +{ok,[{matched,nonode@nohost,2},{saved,x}]}
    +3> lists:seq(1, 3).
    +(<0.89.0>) call lists:seq(1,3)
    +(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
    +[1,2,3]
     %% Add an additional trace pattern
    -4> dbg:session(S, fun() -> dbg:tpl(lists,seq_loop,x) end).
    +4> dbg:session(S, fun() -> dbg:tpl(lists,seq_loop,x) end).
     ok
    -5> lists:seq(1, 3).
    -(<0.89.0>) call lists:seq(1,3)
    -(<0.89.0>) call lists:seq_loop(3,3,[])
    -(<0.89.0>) call lists:seq_loop(1,1,[2,3])
    -(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
    -(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
    -(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
    -[1,2,3]
    -6> dbg:session_destroy(S).
    +5> lists:seq(1, 3).
    +(<0.89.0>) call lists:seq(1,3)
    +(<0.89.0>) call lists:seq_loop(3,3,[])
    +(<0.89.0>) call lists:seq_loop(1,1,[2,3])
    +(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
    +(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
    +(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
    +[1,2,3]
    +6> dbg:session_destroy(S).
     ok

    Trace on Remote Nodes

    The dbg server keeps a list of nodes where tracing should be performed. Whenever a dbg:tp/2 call or a dbg:p/2 call is made, it is executed for all nodes in this list including the local node (except @@ -326,17 +326,17 @@ ignored.

    Example: Using an IP trace port and connecting to it from another node As an example, one can let trace messages be sent over the network to another Erlang node (preferably not distributed), where the formatting occurs.

    On the node stack there exists an Erlang node ant@stack. In the -shell, type the following:

    ant@stack> dbg:tracer(port, dbg:trace_port(ip, 4711)).
    +shell, type the following:

    ant@stack> dbg:tracer(port, dbg:trace_port(ip, 4711)).
     <0.17.0>
    -ant@stack> dbg:p(self(), send).
    -{ok,1}

    All trace messages are now sent to the trace port driver, which in turn listens +ant@stack> dbg:p(self(), send). +{ok,1}

    All trace messages are now sent to the trace port driver, which in turn listens for connections on the TCP/IP port 4711. If we want to see the messages on -another node, preferably on another host, we do like this:

    1> dbg:trace_client(ip, {"stack", 4711}).
    +another node, preferably on another host, we do like this:

    1> dbg:trace_client(ip, {"stack", 4711}).
     <0.42.0>

    If we now send a message from the shell on the node ant@stack, where all sends /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dyntrace.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (738)) --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dyntrace.html 2026-08-21 04:00:26.541341096 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/dyntrace.html 2026-08-21 04:00:26.541341096 +0000 @@ -822,14 +822,14 @@

    Restores the previous state of user tags and their spreading as it was before a call to spread_tag/1.

    Note that the restoring is not limited to the same process; one can utilize this to turn off spreding in one process and restore it in a -newly created process that is is actually going to send messages:

    f() ->
    -    TagData = dyntrace:spread_tag(false),
    -    spawn(fun() ->
    -             dyntrace:restore_tag(TagData),
    -             do_something()
    -          end),
    -    do_something_else(),
    -    dyntrace:restore_tag(TagData).

    Correctly handling user tags and their spreading might take some effort, as +newly created process that is is actually going to send messages:

    f() ->
    +    TagData = dyntrace:spread_tag(false),
    +    spawn(fun() ->
    +             dyntrace:restore_tag(TagData),
    +             do_something()
    +          end),
    +    do_something_else(),
    +    dyntrace:restore_tag(TagData).

    Correctly handling user tags and their spreading might take some effort, as Erlang programs tend to send and receive messages so that sometimes the user tag gets lost due to various things, like double receives or communication with a port (ports do not handle user tags, in the same way as they do not handle @@ -876,12 +876,12 @@ later call to restore_tag/1.

    The file module already spreads tags, so there is no need to manually call this function to get user tags spread to the efile driver through that module.

    The most use of this function would be if one, for example, uses the io module to communicate with an I/O-server for a regular file, such as in the following -example:

    f() ->
    -   {ok, F} = file:open("test.tst", [write]),
    -   Saved = dyntrace:spread_tag(true),
    -   io:format(F, "Hello world!", []),
    -   dyntrace:restore_tag(Saved),
    -   file:close(F).

    In this example, any user tag set in the calling process will be spread to the +example:

    f() ->
    +   {ok, F} = file:open("test.tst", [write]),
    +   Saved = dyntrace:spread_tag(true),
    +   io:format(F, "Hello world!", []),
    +   dyntrace:restore_tag(Saved),
    +   file:close(F).

    In this example, any user tag set in the calling process will be spread to the I/O-server when the io:format/3 call is done.

    /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/instrument.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1679)) --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/instrument.html 2026-08-21 04:00:26.564341246 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/instrument.html 2026-08-21 04:00:26.564341246 +0000 @@ -314,8 +314,8 @@ the one before it.

    The upper bound of the first interval is provided by the function that returned the histogram, and the last interval has no upper bound.

    For example, the histogram below has 40 (message) blocks between 128-256 bytes in size, 78 blocks between 256-512 bytes,2 blocks between 512-1024 bytes, and 2 -blocks between 1-2KB.

    > instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
    -{ok, {128, 0, #{ message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0}, ... } }}
    +blocks between 1-2KB.

    > instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
    +{ok, {128, 0, #{ message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0}, ... } }}
    @@ -455,30 +455,30 @@ block size histograms. Defaults to 128.

  • histogram_width - The number of intervals in the allocated block size histograms. Defaults to 18.

  • flags - Controls how to group the output, for example showing allocations on a per-process basis (when possible) rather than only a -NIF/driver-basis. Defaults to [].

  • Example:

    > instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
    -{ok,{128,0,
    -     #{udp_inet =>
    -           #{driver_event_state => {0,0,0,0,0,0,0,0,0,1,0,0,0,0,0}},
    +NIF/driver-basis. Defaults to [].

    Example:

    > instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
    +{ok,{128,0,
    +     #{udp_inet =>
    +           #{driver_event_state => {0,0,0,0,0,0,0,0,0,1,0,0,0,0,0}},
            system =>
    -           #{heap => {0,0,0,0,20,4,2,2,2,3,0,1,0,0,1},
    -             db_term => {271,3,1,52,80,1,0,0,0,0,0,0,0,0,0},
    -             code => {0,0,0,5,3,6,11,22,19,20,10,2,1,0,0},
    -             binary => {18,0,0,0,7,0,0,1,0,0,0,0,0,0,0},
    -             message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0},
    -             ... }
    +           #{heap => {0,0,0,0,20,4,2,2,2,3,0,1,0,0,1},
    +             db_term => {271,3,1,52,80,1,0,0,0,0,0,0,0,0,0},
    +             code => {0,0,0,5,3,6,11,22,19,20,10,2,1,0,0},
    +             binary => {18,0,0,0,7,0,0,1,0,0,0,0,0,0,0},
    +             message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0},
    +             ... }
            spawn_forker =>
    -           #{driver_select_data_state =>
    -                 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
    -       ram_file_drv => #{drv_binary => {0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}},
    +           #{driver_select_data_state =>
    +                 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
    +       ram_file_drv => #{drv_binary => {0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}},
            prim_file =>
    -           #{process_specific_data => {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    -             nif_trap_export_entry => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0},
    -             monitor_extended => {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
    -             drv_binary => {0,0,0,0,0,0,1,0,3,5,0,0,0,1,0},
    -             binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}},
    +           #{process_specific_data => {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    +             nif_trap_export_entry => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0},
    +             monitor_extended => {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
    +             drv_binary => {0,0,0,0,0,0,1,0,3,5,0,0,0,1,0},
    +             binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}},
            prim_buffer =>
    -           #{nif_internal => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0},
    -             binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}}
    +
    #{nif_internal => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}, + binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}}
    @@ -555,15 +555,15 @@ tied to any particular scheduler. Defaults to all schedulers and the global instance.

  • histogram_start - The upper bound of the first interval in the free block size histograms. Defaults to 512.

  • histogram_width - The number of intervals in the free block size -histograms. Defaults to 14.

  • Example:

    > instrument:carriers(#{ histogram_start => 512, histogram_width => 8 }).
    -{ok,{512,
    -     [{driver_alloc,false,262144,0,
    -                    [{driver_alloc,1,32784}],
    -                    {0,0,0,0,0,0,0,1}},
    -      {binary_alloc,false,32768,0,
    -                    [{binary_alloc,15,4304}],
    -                    {3,0,0,0,1,0,0,0}},
    -      {...}|...]}}
    +histograms. Defaults to 14.

    Example:

    > instrument:carriers(#{ histogram_start => 512, histogram_width => 8 }).
    +{ok,{512,
    +     [{driver_alloc,false,262144,0,
    +                    [{driver_alloc,1,32784}],
    +                    {0,0,0,0,0,0,0,1}},
    +      {binary_alloc,false,32768,0,
    +                    [{binary_alloc,15,4304}],
    +                    {3,0,0,0,1,0,0,0}},
    +      {...}|...]}}
    /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/lttng.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (21492)) --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/lttng.html 2026-08-21 04:00:26.588341402 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/lttng.html 2026-08-21 04:00:26.588341402 +0000 @@ -96,46 +96,46 @@ information on how to install LTTng on your system.

    After LTTng is properly installed on the system Erlang/OTP can be built with LTTng support.

    $ ./configure --with-dynamic-trace=lttng
     $ make

    Dyntrace Tracepoints

    All tracepoints are in the domain of org_erlang_dyntrace

    All Erlang types are the string equivalent in LTTng.

    process_spawn

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • parent : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"

    Available through erlang:trace/3 with trace flag procs and -{tracer,dyntrace,[]} as tracer module.

    Example:

    process_spawn: { cpu_id = 3 }, { pid = "<0.131.0>", parent = "<0.130.0>", entry = "erlang:apply/2" }

    process_link

    • to : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • from : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • type : string :: "link" | "unlink"

    Available through erlang:trace/3 with trace flag procs and +{tracer,dyntrace,[]} as tracer module.

    Example:

    process_spawn: { cpu_id = 3 }, { pid = "<0.131.0>", parent = "<0.130.0>", entry = "erlang:apply/2" }

    process_link

    • to : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • from : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • type : string :: "link" | "unlink"

    Available through erlang:trace/3 with trace flag procs and {tracer,dyntrace,[]} as tracer module.

    Example:

    process_link: { cpu_id = 3 }, { from = "<0.130.0>", to = "<0.131.0>", type = "link" }

    process_exit

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • reason : string :: Exit reason. Ex. "normal"

    Available through erlang:trace/3 with trace flag procs and -{tracer,dyntrace,[]} as tracer module.

    Example:

    process_exit: { cpu_id = 3 }, { pid = "<0.130.0>", reason = "normal" }

    process_register

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • name : string :: Registered name. Ex. "logger"
    • type : string :: "register" | "unregister"

    Example:

    process_register: { cpu_id = 0 }, { pid = "<0.128.0>", name = "dyntrace_lttng_SUITE" type = "register" }

    process_scheduled

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"
    • type : string :: +{tracer,dyntrace,[]} as tracer module.

      Example:

      process_exit: { cpu_id = 3 }, { pid = "<0.130.0>", reason = "normal" }

      process_register

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • name : string :: Registered name. Ex. "logger"
      • type : string :: "register" | "unregister"

      Example:

      process_register: { cpu_id = 0 }, { pid = "<0.128.0>", name = "dyntrace_lttng_SUITE" type = "register" }

      process_scheduled

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • entry : string :: Code Location. Ex. "lists:sort/1"
      • type : string :: "in" | "out" | "in_exiting" | "out_exiting" | "out_exited"

      Available through erlang:trace/3 with trace flag running and -{tracer,dyntrace,[]} as tracer module.

      Example:

      process_scheduled: { cpu_id = 0 }, { pid = "<0.136.0>", entry = "erlang:apply/2", type = "in" }

      port_open

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • port : string :: Port ID. Ex. "#Port<0.1031>"

      Available through erlang:trace/3 with trace flag ports and +{tracer,dyntrace,[]} as tracer module.

      Example:

      process_scheduled: { cpu_id = 0 }, { pid = "<0.136.0>", entry = "erlang:apply/2", type = "in" }

      port_open

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • port : string :: Port ID. Ex. "#Port<0.1031>"

      Available through erlang:trace/3 with trace flag ports and {tracer,dyntrace,[]} as tracer module.

      Example:

      port_open: { cpu_id = 5 }, { pid = "<0.131.0>", driver = "'/bin/sh -s unix:cmd'", port = "#Port<0.1887>" }

      port_exit

      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • reason : string :: Exit reason. Ex. "normal"

      Available through erlang:trace/3 with trace flag ports and {tracer,dyntrace,[]} as tracer module.

      Example:

      port_exit: { cpu_id = 5 }, { port = "#Port<0.1887>", reason = "normal" }

      port_link

      • to : string :: Process ID. Ex. "<0.131.0>"
      • from : string :: Process ID. Ex. "<0.131.0>"
      • type : string :: "link" | "unlink"

      Available through erlang:trace/3 with trace flag ports and -{tracer,dyntrace,[]} as tracer module.

      Example:

      port_link: { cpu_id = 5 }, { from = "#Port<0.1887>", to = "<0.131.0>", type = "unlink" }

      port_scheduled

      Available through erlang:trace/3 with trace flag running and +{tracer,dyntrace,[]} as tracer module.

      Example:

      port_link: { cpu_id = 5 }, { from = "#Port<0.1887>", to = "<0.131.0>", type = "unlink" }

      port_scheduled

      Available through erlang:trace/3 with trace flag running and {tracer,dyntrace,[]} as tracer module.

      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • entry : string :: Callback. Ex. "open"
      • type : string :: -"in" | "out" | "in_exiting" | "out_exiting" | "out_exited"

      Example:

      port_scheduled: { cpu_id = 5 }, { pid = "#Port<0.1905>", entry = "close", type = "out" }

      Available through erlang:trace/3 with trace flag running and +"in" | "out" | "in_exiting" | "out_exiting" | "out_exited"

    Example:

    port_scheduled: { cpu_id = 5 }, { pid = "#Port<0.1905>", entry = "close", type = "out" }

    Available through erlang:trace/3 with trace flag running and {tracer,dyntrace,[]} as tracer module.

    function_call

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"
    • depth : integer :: Stack depth. Ex. 0

    Available through erlang:trace/3 with trace flag call and -{tracer,dyntrace,[]} as tracer module.

    Example:

    function_call: { cpu_id = 5 }, { pid = "<0.145.0>", entry = "dyntrace_lttng_SUITE:'-t_call/1-fun-1-'/0", depth = 0 }

    function_return

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"
    • depth : integer :: Stack depth. Ex. 0

    Available through erlang:trace/3 with trace flag call or return_to and -{tracer,dyntrace,[]} as tracer module.

    Example:

    function_return: { cpu_id = 5 }, { pid = "<0.145.0>", entry = "dyntrace_lttng_SUITE:waiter/0", depth = 0 }

    function_exception

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"
    • class : string :: Error reason. Ex. "error"

    Available through erlang:trace/3 with trace flag call and -{tracer,dyntrace,[]} as tracer module.

    Example:

    function_exception: { cpu_id = 5 }, { pid = "<0.144.0>", entry = "t:call_exc/1", class = "error" }

    message_send

    • from : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • to : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • message : string :: Message sent. Ex. "{<0.162.0>,ok}"

    Available through erlang:trace/3 with trace flag send and +{tracer,dyntrace,[]} as tracer module.

    Example:

    function_call: { cpu_id = 5 }, { pid = "<0.145.0>", entry = "dyntrace_lttng_SUITE:'-t_call/1-fun-1-'/0", depth = 0 }

    function_return

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"
    • depth : integer :: Stack depth. Ex. 0

    Available through erlang:trace/3 with trace flag call or return_to and +{tracer,dyntrace,[]} as tracer module.

    Example:

    function_return: { cpu_id = 5 }, { pid = "<0.145.0>", entry = "dyntrace_lttng_SUITE:waiter/0", depth = 0 }

    function_exception

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"
    • class : string :: Error reason. Ex. "error"

    Available through erlang:trace/3 with trace flag call and +{tracer,dyntrace,[]} as tracer module.

    Example:

    function_exception: { cpu_id = 5 }, { pid = "<0.144.0>", entry = "t:call_exc/1", class = "error" }

    message_send

    • from : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • to : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • message : string :: Message sent. Ex. "{<0.162.0>,ok}"

    Available through erlang:trace/3 with trace flag send and {tracer,dyntrace,[]} as tracer module.

    Example:

    message_send: { cpu_id = 3 }, { from = "#Port<0.1938>", to = "<0.160.0>", message = "{#Port<0.1938>,eof}" }

    message_receive

    • to : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • message : string :: Message received. Ex. "{<0.162.0>,ok}"

    Available through erlang:trace/3 with trace flag 'receive' and {tracer,dyntrace,[]} as tracer module.

    Example:

    message_receive: { cpu_id = 7 }, { to = "<0.167.0>", message = "{<0.165.0>,ok}" }

    gc_minor_start

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • need : integer :: Heap need. Ex. 2
    • heap : integer :: Young heap word size. Ex. 233
    • old_heap : integer :: Old heap word size. Ex. 233

    Available through erlang:trace/3 with trace flag garbage_collection and -{tracer,dyntrace,[]} as tracer module.

    Example:

    gc_minor_start: { cpu_id = 0 }, { pid = "<0.172.0>", need = 0, heap = 610, old_heap = 0 }

    gc_minor_end

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • reclaimed : integer :: Heap reclaimed. Ex. 2
    • heap : integer :: Young heap word size. Ex. 233
    • old_heap : integer :: Old heap word size. Ex. 233

    Available through erlang:trace/3 with trace flag garbage_collection and -{tracer,dyntrace,[]} as tracer module.

    Example:

    gc_minor_end: { cpu_id = 0 }, { pid = "<0.172.0>", reclaimed = 120, heap = 1598, old_heap = 1598 }

    gc_major_start

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • need : integer :: Heap need. Ex. 2
    • heap : integer :: Young heap word size. Ex. 233
    • old_heap : integer :: Old heap word size. Ex. 233

    Available through erlang:trace/3 with trace flag garbage_collection and -{tracer,dyntrace,[]} as tracer module.

    Example:

    gc_major_start: { cpu_id = 0 }, { pid = "<0.172.0>", need = 8, heap = 2586, old_heap = 1598 }

    gc_major_end

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • reclaimed : integer :: Heap reclaimed. Ex. 2
    • heap : integer :: Young heap word size. Ex. 233
    • old_heap : integer :: Old heap word size. Ex. 233

    Available through erlang:trace/3 with trace flag garbage_collection and -{tracer,dyntrace,[]} as tracer module.

    Example:

    gc_major_end: { cpu_id = 0 }, { pid = "<0.172.0>", reclaimed = 240, heap = 4185, old_heap = 0 }

    BEAM Tracepoints

    All tracepoints are in the domain of org_erlang_otp

    All Erlang types are the string equivalent in LTTng.

    driver_init

    • driver : string :: Driver name. Ex. "tcp_inet"
    • major : integer :: Major version. Ex. 3
    • minor : integer :: Minor version. Ex. 1
    • flags : integer :: Flags. Ex. 1

    Example:

    driver_init: { cpu_id = 2 }, { driver = "caller_drv", major = 3, minor = 3, flags = 1 }

    driver_start

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • driver : string :: Driver name. Ex. "tcp_inet"
    • port : string :: Port ID. Ex. "#Port<0.1031>"

    Example:

    driver_start: { cpu_id = 2 }, { pid = "<0.198.0>", driver = "caller_drv", port = "#Port<0.3676>" }

    driver_output

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"
    • bytes : integer :: Size of data returned. Ex. 82

    Example:

    driver_output: { cpu_id = 2 }, { pid = "<0.198.0>", port = "#Port<0.3677>", driver = "/bin/sh -s unix:cmd", bytes = 36 }

    driver_outputv

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"
    • bytes : integer :: Size of data returned. Ex. 82

    Example:

    driver_outputv: { cpu_id = 5 }, { pid = "<0.194.0>", port = "#Port<0.3663>", driver = "tcp_inet", bytes = 3 }

    driver_ready_input

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_ready_input: { cpu_id = 5 }, { pid = "<0.189.0>", port = "#Port<0.3637>", driver = "inet_gethost 4 " }

    driver_ready_output

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_ready_output: { cpu_id = 5 }, { pid = "<0.194.0>", port = "#Port<0.3663>", driver = "tcp_inet" }

    driver_timeout

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_timeout: { cpu_id = 5 }, { pid = "<0.196.0>", port = "#Port<0.3664>", driver = "tcp_inet" }

    driver_stop_select

    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_stop_select: { cpu_id = 5 }, { driver = "unknown" }

    driver_flush

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_flush: { cpu_id = 7 }, { pid = "<0.204.0>", port = "#Port<0.3686>", driver = "tcp_inet" }

    driver_stop

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_stop: { cpu_id = 5 }, { pid = "[]", port = "#Port<0.3673>", driver = "tcp_inet" }

    driver_process_exit

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    driver_ready_async

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_ready_async: { cpu_id = 3 }, { pid = "<0.181.0>", port = "#Port<0.3622>", driver = "tcp_inet" }

    driver_call

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"
    • command : integer :: Command integer. Ex. 1
    • bytes : integer :: Size of data returned. Ex. 82

    Example:

    driver_call: { cpu_id = 2 }, { pid = "<0.202.0>", port = "#Port<0.3676>", driver = "caller_drv", command = 0, bytes = 2 }

    driver_control

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"
    • command : integer :: Command integer. Ex. 1
    • bytes : integer :: Size of data returned. Ex. 82

    Example:

    driver_control: { cpu_id = 3 }, { pid = "<0.32767.8191>", port = "#Port<0.0>", driver = "forker", command = 83, bytes = 32 }

    carrier_create

    • type : string :: Carrier type. Ex. "ets_alloc"
    • instance : integer :: Allocator instance. Ex. 1
    • size : integer :: Carrier size. Ex. 262144
    • mbc_carriers : integer :: Number of multiblock carriers in instance. Ex. 3
    • mbc_carriers_size : integer :: Total size of multiblock blocks carriers in +{tracer,dyntrace,[]} as tracer module.

      Example:

      gc_minor_start: { cpu_id = 0 }, { pid = "<0.172.0>", need = 0, heap = 610, old_heap = 0 }

      gc_minor_end

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • reclaimed : integer :: Heap reclaimed. Ex. 2
      • heap : integer :: Young heap word size. Ex. 233
      • old_heap : integer :: Old heap word size. Ex. 233

      Available through erlang:trace/3 with trace flag garbage_collection and +{tracer,dyntrace,[]} as tracer module.

      Example:

      gc_minor_end: { cpu_id = 0 }, { pid = "<0.172.0>", reclaimed = 120, heap = 1598, old_heap = 1598 }

      gc_major_start

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • need : integer :: Heap need. Ex. 2
      • heap : integer :: Young heap word size. Ex. 233
      • old_heap : integer :: Old heap word size. Ex. 233

      Available through erlang:trace/3 with trace flag garbage_collection and +{tracer,dyntrace,[]} as tracer module.

      Example:

      gc_major_start: { cpu_id = 0 }, { pid = "<0.172.0>", need = 8, heap = 2586, old_heap = 1598 }

      gc_major_end

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • reclaimed : integer :: Heap reclaimed. Ex. 2
      • heap : integer :: Young heap word size. Ex. 233
      • old_heap : integer :: Old heap word size. Ex. 233

      Available through erlang:trace/3 with trace flag garbage_collection and +{tracer,dyntrace,[]} as tracer module.

      Example:

      gc_major_end: { cpu_id = 0 }, { pid = "<0.172.0>", reclaimed = 240, heap = 4185, old_heap = 0 }

      BEAM Tracepoints

      All tracepoints are in the domain of org_erlang_otp

      All Erlang types are the string equivalent in LTTng.

      driver_init

      • driver : string :: Driver name. Ex. "tcp_inet"
      • major : integer :: Major version. Ex. 3
      • minor : integer :: Minor version. Ex. 1
      • flags : integer :: Flags. Ex. 1

      Example:

      driver_init: { cpu_id = 2 }, { driver = "caller_drv", major = 3, minor = 3, flags = 1 }

      driver_start

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • port : string :: Port ID. Ex. "#Port<0.1031>"

      Example:

      driver_start: { cpu_id = 2 }, { pid = "<0.198.0>", driver = "caller_drv", port = "#Port<0.3676>" }

      driver_output

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • bytes : integer :: Size of data returned. Ex. 82

      Example:

      driver_output: { cpu_id = 2 }, { pid = "<0.198.0>", port = "#Port<0.3677>", driver = "/bin/sh -s unix:cmd", bytes = 36 }

      driver_outputv

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • bytes : integer :: Size of data returned. Ex. 82

      Example:

      driver_outputv: { cpu_id = 5 }, { pid = "<0.194.0>", port = "#Port<0.3663>", driver = "tcp_inet", bytes = 3 }

      driver_ready_input

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_ready_input: { cpu_id = 5 }, { pid = "<0.189.0>", port = "#Port<0.3637>", driver = "inet_gethost 4 " }

      driver_ready_output

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_ready_output: { cpu_id = 5 }, { pid = "<0.194.0>", port = "#Port<0.3663>", driver = "tcp_inet" }

      driver_timeout

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_timeout: { cpu_id = 5 }, { pid = "<0.196.0>", port = "#Port<0.3664>", driver = "tcp_inet" }

      driver_stop_select

      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_stop_select: { cpu_id = 5 }, { driver = "unknown" }

      driver_flush

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_flush: { cpu_id = 7 }, { pid = "<0.204.0>", port = "#Port<0.3686>", driver = "tcp_inet" }

      driver_stop

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_stop: { cpu_id = 5 }, { pid = "[]", port = "#Port<0.3673>", driver = "tcp_inet" }

      driver_process_exit

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      driver_ready_async

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_ready_async: { cpu_id = 3 }, { pid = "<0.181.0>", port = "#Port<0.3622>", driver = "tcp_inet" }

      driver_call

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • command : integer :: Command integer. Ex. 1
      • bytes : integer :: Size of data returned. Ex. 82

      Example:

      driver_call: { cpu_id = 2 }, { pid = "<0.202.0>", port = "#Port<0.3676>", driver = "caller_drv", command = 0, bytes = 2 }

      driver_control

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • command : integer :: Command integer. Ex. 1
      • bytes : integer :: Size of data returned. Ex. 82

      Example:

      driver_control: { cpu_id = 3 }, { pid = "<0.32767.8191>", port = "#Port<0.0>", driver = "forker", command = 83, bytes = 32 }

      carrier_create

      • type : string :: Carrier type. Ex. "ets_alloc"
      • instance : integer :: Allocator instance. Ex. 1
      • size : integer :: Carrier size. Ex. 262144
      • mbc_carriers : integer :: Number of multiblock carriers in instance. Ex. 3
      • mbc_carriers_size : integer :: Total size of multiblock blocks carriers in instance. Ex. 1343488
      • mbc_blocks : integer :: Number of multiblock blocks in instance. Ex. 122
      • mbc_blocks_size : integer :: Total size of all multiblock blocks in instance. Ex. 285296
      • sbc_carriers : integer :: Number of singleblock carriers in instance. Ex. 1
      • sbc_carriers_size : integer :: Total size of singleblock blocks carriers in instance. Ex. 1343488
      • sbc_blocks : integer :: Number of singleblocks in instance. Ex. 1
      • sbc_blocks_size : integer :: Total size of all singleblock blocks in -instance. Ex. 285296

      Example:

      carrier_create: { cpu_id = 2 }, { type = "ets_alloc", instance = 7, size = 2097152, mbc_carriers = 4, mbc_carriers_size = 3440640, mbc_blocks = 526, mbc_blocks_size = 1278576, sbc_carriers = 0, sbc_carriers_size = 0, sbc_blocks = 0, sbc_blocks_size = 0 }

      carrier_destroy

      • type : string :: Carrier type. Ex. "ets_alloc"
      • instance : integer :: Allocator instance. Ex. 1
      • size : integer :: Carrier size. Ex. 262144
      • mbc_carriers : integer :: Number of multiblock carriers in instance. Ex. 3
      • mbc_carriers_size : integer :: Total size of multiblock blocks carriers in +instance. Ex. 285296

      Example:

      carrier_create: { cpu_id = 2 }, { type = "ets_alloc", instance = 7, size = 2097152, mbc_carriers = 4, mbc_carriers_size = 3440640, mbc_blocks = 526, mbc_blocks_size = 1278576, sbc_carriers = 0, sbc_carriers_size = 0, sbc_blocks = 0, sbc_blocks_size = 0 }

      carrier_destroy

      • type : string :: Carrier type. Ex. "ets_alloc"
      • instance : integer :: Allocator instance. Ex. 1
      • size : integer :: Carrier size. Ex. 262144
      • mbc_carriers : integer :: Number of multiblock carriers in instance. Ex. 3
      • mbc_carriers_size : integer :: Total size of multiblock blocks carriers in instance. Ex. 1343488
      • mbc_blocks : integer :: Number of multiblock blocks in instance. Ex. 122
      • mbc_blocks_size : integer :: Total size of all multiblock blocks in instance. Ex. 285296
      • sbc_carriers : integer :: Number of singleblock carriers in instance. Ex. 1
      • sbc_carriers_size : integer :: Total size of singleblock blocks carriers in instance. Ex. 1343488
      • sbc_blocks : integer :: Number of singleblocks in instance. Ex. 1
      • sbc_blocks_size : integer :: Total size of all singleblock blocks in -instance. Ex. 285296

      Example:

      carrier_destroy: { cpu_id = 6 }, { type = "ets_alloc", instance = 7, size = 262144, mbc_carriers = 3, mbc_carriers_size = 3178496, mbc_blocks = 925, mbc_blocks_size = 2305336, sbc_carriers = 0, sbc_carriers_size = 0, sbc_blocks = 0, sbc_blocks_size = 0 }

      carrier_pool_put

      • type : string :: Carrier type. Ex. "ets_alloc"
      • instance : integer :: Allocator instance. Ex. 1
      • size : integer :: Carrier size. Ex. 262144

      Example:

      carrier_pool_put: { cpu_id = 3 }, { type = "ets_alloc", instance = 5, size = 1048576 }

      carrier_pool_get

      • type : string :: Carrier type. Ex. "ets_alloc"
      • instance : integer :: Allocator instance. Ex. 1
      • size : integer :: Carrier size. Ex. 262144

      Example:

      carrier_pool_get: { cpu_id = 7 }, { type = "ets_alloc", instance = 4, size = 3208 }

      Example of process tracing

      An example of process tracing of os_mon and friends.

      Clean start of lttng in a bash shell.

      $ lttng create erlang-demo
      +instance. Ex. 285296

    Example:

    carrier_destroy: { cpu_id = 6 }, { type = "ets_alloc", instance = 7, size = 262144, mbc_carriers = 3, mbc_carriers_size = 3178496, mbc_blocks = 925, mbc_blocks_size = 2305336, sbc_carriers = 0, sbc_carriers_size = 0, sbc_blocks = 0, sbc_blocks_size = 0 }

    carrier_pool_put

    • type : string :: Carrier type. Ex. "ets_alloc"
    • instance : integer :: Allocator instance. Ex. 1
    • size : integer :: Carrier size. Ex. 262144

    Example:

    carrier_pool_put: { cpu_id = 3 }, { type = "ets_alloc", instance = 5, size = 1048576 }

    carrier_pool_get

    • type : string :: Carrier type. Ex. "ets_alloc"
    • instance : integer :: Allocator instance. Ex. 1
    • size : integer :: Carrier size. Ex. 262144

    Example:

    carrier_pool_get: { cpu_id = 7 }, { type = "ets_alloc", instance = 4, size = 3208 }

    Example of process tracing

    An example of process tracing of os_mon and friends.

    Clean start of lttng in a bash shell.

    $ lttng create erlang-demo
     Spawning a session daemon
     Session erlang-demo created.
     Traces will be written in /home/egil/lttng-traces/erlang-demo-20160526-165920

    Start an Erlang node with lttng enabled.

    $ erl
     Erlang/OTP 19 [erts-8.0] [source-4d7b24d] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [lttng]
     
     Eshell V8.0  (abort with ^G)
    -1>

    Load the dyntrace module.

    1> l(dyntrace).
    -{module,dyntrace}

    All tracepoints via dyntrace are now visible and can be listed through +1>

    Load the dyntrace module.

    1> l(dyntrace).
    +{module,dyntrace}

    All tracepoints via dyntrace are now visible and can be listed through lttng list -u.

    Enable the process_register LTTng tracepoint for Erlang.

    $ lttng enable-event -u org_erlang_dyntrace:process_register
    -UST event org_erlang_dyntrace:process_register created in channel channel0

    Enable process tracing for new processes and use dyntrace as tracer backend.

    2> erlang:trace(new,true,[procs,{tracer,dyntrace,[]}]).
    +UST event org_erlang_dyntrace:process_register created in channel channel0

    Enable process tracing for new processes and use dyntrace as tracer backend.

    2> erlang:trace(new,true,[procs,{tracer,dyntrace,[]}]).
     0

    Start LTTng tracing.

    $ lttng start
     Tracing started for session erlang-demo

    Start the os_mon application in Erlang.

    3> application:ensure_all_started(os_mon).
     {ok,[sasl,os_mon]}

    Stop LTTng tracing and view the result.

    $ lttng stop
    /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/msacc.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1991))
    --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/msacc.html	2026-08-21 04:00:26.617341591 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/msacc.html	2026-08-21 04:00:26.618341597 +0000
    @@ -96,9 +96,9 @@
     

    Convenience functions for microstate accounting

    This module implements some convenience functions for analyzing microstate accounting data. For details about how to use the basic API and what the different states represent, see -erlang:statistics(microstate_accounting).

    Basic Scenario

    1> msacc:start(1000).
    +erlang:statistics(microstate_accounting).

    Basic Scenario

    1> msacc:start(1000).
     ok
    -2> msacc:print().
    +2> msacc:print().
     Average thread real-time    : 1000513 us
     Accumulated system run-time :    2213 us
     Average scheduler run-time  :    1076 us
    @@ -106,11 +106,11 @@
             Thread      aux check_io emulator       gc    other     port    sleep
     
     Stats per thread:
    -     async( 0)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
    -     async( 1)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
    -       aux( 1)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%   99.99%
    - scheduler( 1)    0.00%    0.03%    0.13%    0.00%    0.01%    0.00%   99.82%
    - scheduler( 2)    0.00%    0.00%    0.00%    0.00%    0.03%    0.00%   99.97%
    +     async( 0)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
    +     async( 1)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
    +       aux( 1)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%   99.99%
    + scheduler( 1)    0.00%    0.03%    0.13%    0.00%    0.01%    0.00%   99.82%
    + scheduler( 2)    0.00%    0.00%    0.00%    0.00%    0.03%    0.00%   99.97%
     
     Stats per type:
              async    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
    @@ -910,7 +910,7 @@
     this can be verbose. See the top of this reference manual for a brief
     description of what the fields mean.

    It is possible to print more specific types of statistics by first manipulating the DataOrStats using stats/2. For instance if you want to print the -percentage of run-time for each thread you can do:

    msacc:print(msacc:stats(runtime, msacc:stats())).

    If you want to only print run-time per thread type you can do:

    msacc:print(msacc:stats(type, msacc:stats(runtime, msacc:stats()))).

    Options

    • system - Print percentage of time spent in each state out of system time +percentage of run-time for each thread you can do:

      msacc:print(msacc:stats(runtime, msacc:stats())).

      If you want to only print run-time per thread type you can do:

      msacc:print(msacc:stats(type, msacc:stats(runtime, msacc:stats()))).

      Options

      • system - Print percentage of time spent in each state out of system time as well as thread time. Default: false.
      /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (5952)) --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/notes.html 2026-08-21 04:00:26.658341858 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/notes.html 2026-08-21 04:00:26.646341780 +0000 @@ -89,9 +89,9 @@ -

      This document describes the changes made to the Runtime_Tools application.

      Runtime_Tools 2.3.1

      Improvements and New Features

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      Runtime_Tools 2.3

      Fixed Bugs and Malfunctions

      • NIFs and linked-in drivers are now loadable when running in an Erlang source tree on Windows.

        Own Id: OTP-19686 Aux Id: PR-9969

      Improvements and New Features

      • The default tracer is now aware that it is started by a remote shell (-remsh), in which case the traces will be sent to the remote group_leader to make the traces visible in the remote shell.

        Own Id: OTP-19648 Aux Id: PR-9589

      • A User's Guide to dbg is now available in the documentation.

        Own Id: OTP-19655 Aux Id: PR-9853

      Runtime_Tools 2.2

      Improvements and New Features

      • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

        All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

        -type meter() :: integer().
        --type foot() :: integer().

        Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

        -nominal meter() :: integer().
        --nominal foot() :: integer().

        More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

        Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

        Own Id: OTP-19364 Aux Id: PR-9079

      • When compiling C/C++ code on Unix systems, the compiler hardening flags suggested by the Open Source Security Foundation are now enabled by default. To disable them, pass --disable-security-hardening-flags to configure.

        Own Id: OTP-19519 Aux Id: PR-9441

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      • With this change observer will use cheaper iterators to avoid locking when not necessary.

        Own Id: OTP-19584 Aux Id: PR-9711

      Runtime_Tools 2.1.1

      Fixed Bugs and Malfunctions

      • Fixed a bug where dbg sessions on remote nodes were terminated prematurely.

        Own Id: OTP-19188 Aux Id: PR-8692

      Runtime_Tools 2.1

      Improvements and New Features

      • The instrument module can now track allocations on a per-process or per-port basis.

        Own Id: OTP-18577 Aux Id: PR-7236

      • The new function proc_lib:set_label/1 can be used to add a descriptive term to any process that does not have a registered name. The name will be shown by tools such as c:i/0, observer, and it will be included in crash reports produced by processes using gen_server, gen_statem, gen_event, and gen_fsm.

        The label for a process can be retrieved by calling proc_lib:get_label/1.

        Note that those functions work on any process, not only processes that use proc_lib.

        Example:

        1> self().
        +

        This document describes the changes made to the Runtime_Tools application.

        Runtime_Tools 2.3.1

        Improvements and New Features

        • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

          A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

          make release_docs places the documentation in the released code under the doc folder.

          make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

          The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

          Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

          Improves the source Software-Bill-of-Materials

          • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
          • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
          • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

          Own Id: OTP-19886 Aux Id: PR-10434

        Runtime_Tools 2.3

        Fixed Bugs and Malfunctions

        • NIFs and linked-in drivers are now loadable when running in an Erlang source tree on Windows.

          Own Id: OTP-19686 Aux Id: PR-9969

        Improvements and New Features

        • The default tracer is now aware that it is started by a remote shell (-remsh), in which case the traces will be sent to the remote group_leader to make the traces visible in the remote shell.

          Own Id: OTP-19648 Aux Id: PR-9589

        • A User's Guide to dbg is now available in the documentation.

          Own Id: OTP-19655 Aux Id: PR-9853

        Runtime_Tools 2.2

        Improvements and New Features

        • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

          All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

          -type meter() :: integer().
          +-type foot() :: integer().

          Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

          -nominal meter() :: integer().
          +-nominal foot() :: integer().

          More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

          Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

          Own Id: OTP-19364 Aux Id: PR-9079

        • When compiling C/C++ code on Unix systems, the compiler hardening flags suggested by the Open Source Security Foundation are now enabled by default. To disable them, pass --disable-security-hardening-flags to configure.

          Own Id: OTP-19519 Aux Id: PR-9441

        • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

          Own Id: OTP-19575 Aux Id: PR-9670

        • With this change observer will use cheaper iterators to avoid locking when not necessary.

          Own Id: OTP-19584 Aux Id: PR-9711

        Runtime_Tools 2.1.1

        Fixed Bugs and Malfunctions

        • Fixed a bug where dbg sessions on remote nodes were terminated prematurely.

          Own Id: OTP-19188 Aux Id: PR-8692

        Runtime_Tools 2.1

        Improvements and New Features

        • The instrument module can now track allocations on a per-process or per-port basis.

          Own Id: OTP-18577 Aux Id: PR-7236

        • The new function proc_lib:set_label/1 can be used to add a descriptive term to any process that does not have a registered name. The name will be shown by tools such as c:i/0, observer, and it will be included in crash reports produced by processes using gen_server, gen_statem, gen_event, and gen_fsm.

          The label for a process can be retrieved by calling proc_lib:get_label/1.

          Note that those functions work on any process, not only processes that use proc_lib.

          Example:

          1> self().
           <0.90.0>
           2> proc_lib:set_label(my_label).
           ok
          /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text)
          --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
          +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
          @@ -4,10 +4,10 @@
                    version="3.0">
             
               runtime_tools - 2.3.1
          -    urn:uuid:36e9f835-835d-a455-2fa2-8f85d565bab9
          +    urn:uuid:4e318644-d67f-435a-f589-da91e3ded317
               en
           
          -    2026-08-21T03:47:47Z
          +    2042-09-22T17:06:27Z
           
             
             
          /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/dbg_guide.xhtml differs (HTML document, ASCII text, with very long lines (1693))
          --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/dbg_guide.xhtml	2026-08-05 05:56:49.000000000 +0000
          +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/dbg_guide.xhtml	2026-08-05 05:56:49.000000000 +0000
          @@ -20,22 +20,22 @@
           

          The dbg module in Erlang provides a text-based interface for tracing function calls, processes, ports, and messages. It simplifies the use of the underlying trace:process/4, trace:port/4, and trace:function/4 BIFs (Built-In Functions). This guide will walk you through the basics of using dbg for your Erlang applications.

          This facility is useful for both quick debugging sessions in the shell and for more structured system testing, especially where other tools might have too much performance impact.

          Quick Start

          To trace a call to a function with minimal fuss, call dbg:c(Module, Name, Arguments). It starts a temporary trace receiver, enables all trace flags, and calls the designated function from a temporary process. For example, here is how to trace a call -to application:which_applications/0:

          1> dbg:c(application, which_applications, []).
          -(<0.92.0>) <0.45.0> ! {'$gen_call',{<0.92.0>,
          -                                    [alias|
          -                                     #Ref<0.0.11779.270031856.1478295555.230456>]},
          -                                   which_applications} (Timestamp: {1710,
          +to application:which_applications/0:

          1> dbg:c(application, which_applications, []).
          +(<0.92.0>) <0.45.0> ! {'$gen_call',{<0.92.0>,
          +                                    [alias|
          +                                     #Ref<0.0.11779.270031856.1478295555.230456>]},
          +                                   which_applications} (Timestamp: {1710,
                                                                               847802,
          -                                                                    479222})
          -(<0.92.0>) out {gen,do_call,4} (Timestamp: {1710,847802,479231})
          -(<0.92.0>) in {gen,do_call,4} (Timestamp: {1710,847802,479271})
          -(<0.92.0>) << {[alias|#Ref<0.0.11779.270031856.1478295555.230456>],
          -               [{stdlib,"ERTS  CXC 138 10","5.2.1"},
          -                {kernel,"ERTS  CXC 138 10","9.2.2"}]} (Timestamp: {1710,
          +                                                                    479222})
          +(<0.92.0>) out {gen,do_call,4} (Timestamp: {1710,847802,479231})
          +(<0.92.0>) in {gen,do_call,4} (Timestamp: {1710,847802,479271})
          +(<0.92.0>) << {[alias|#Ref<0.0.11779.270031856.1478295555.230456>],
          +               [{stdlib,"ERTS  CXC 138 10","5.2.1"},
          +                {kernel,"ERTS  CXC 138 10","9.2.2"}]} (Timestamp: {1710,
                                                                              847802,
          -                                                                   479274})
          -[{stdlib,"ERTS  CXC 138 10","5.2.1"},
          - {kernel,"ERTS  CXC 138 10","9.2.2"}]

          In this example, four trace events are generated:

          • A send event (!) for the sending of a request from the current process + 479274}) +[{stdlib,"ERTS CXC 138 10","5.2.1"}, + {kernel,"ERTS CXC 138 10","9.2.2"}]

          In this example, four trace events are generated:

          • A send event (!) for the sending of a request from the current process to the application_controller process.
          • A schedule-out event (out) when the current process schedules out while waiting in a receive for the reply to arrive.
          • A schedule-in event (in) when the current process is scheduled in when reply has arrived.
          • A receive event (<<) when the current process retrieves the reply from @@ -44,8 +44,8 @@ tracer and set the trace flags of your choice on the processes you want to trace. This is useful, when there is a complex system of processes, ports or nodes interacting where dbg:c/3 is to blunt.

            Starting a Tracer (dbg:tracer/0,2)

            First, you need to start a tracer process that will receive and display trace -messages.

            1> dbg:tracer().  % Start the default trace message receiver
            -{ok,<0.90.0>}     % <0.90.0> is the PID of the tracer process

            This starts a server on the local node that will be the recipient of all trace +messages.

            1> dbg:tracer().  % Start the default trace message receiver
            +{ok,<0.90.0>}     % <0.90.0> is the PID of the tracer process

            This starts a server on the local node that will be the recipient of all trace messages. It uses a default handler that prints formatted trace messages to the Erlang shell.

            If you need a custom tracer other than the default, you can create a tracer using dbg:tracer(Type, Data):

            • Type = process: Data is {HandlerFun, InitialState}. HandlerFun is @@ -76,18 +76,18 @@ case of a single pid exactly 1). The specification of matched processes is {matched, Node, N}. If the remote processor call (using rpc) to a remote node fails, the rpc error message is returned as the fourth element in the -tuple and the number of matched processes is 0.

              Example: Trace messages and process events for a specific process

              1> Pid = spawn(fun() -> receive {From,Msg} -> From ! Msg end end).
              +tuple and the number of matched processes is 0.

              Example: Trace messages and process events for a specific process

              1> Pid = spawn(fun() -> receive {From,Msg} -> From ! Msg end end).
               <0.90.0>
              -2> dbg:tracer().
              -{ok,<0.92.0>}
              -3> dbg:p(Pid, [m,procs]). % Trace messages and process events for Pid
              -{ok,[{matched,nonode@nohost,1}]}
              -4> Pid ! {self(),hello}.
              -(<0.90.0>) << {<0.88.0>,hello} % Received by Pid
              -{<0.88.0>,hello}
              -(<0.90.0>) <0.88.0> ! hello    % Sent by Pid
              -(<0.90.0>) exit normal         % Process event: Pid exited
              -5> flush().
              +2> dbg:tracer().
              +{ok,<0.92.0>}
              +3> dbg:p(Pid, [m,procs]). % Trace messages and process events for Pid
              +{ok,[{matched,nonode@nohost,1}]}
              +4> Pid ! {self(),hello}.
              +(<0.90.0>) << {<0.88.0>,hello} % Received by Pid
              +{<0.88.0>,hello}
              +(<0.90.0>) <0.88.0> ! hello    % Sent by Pid
              +(<0.90.0>) exit normal         % Process event: Pid exited
              +5> flush().
               Shell got hello
               ok

              Tracing Function Calls (dbg:tp/2,3,4, dbg:tpl/2,3,4)

              To trace function calls, you need to:

              1. Enable the c/call flag for the process(es) that will make the calls (using dbg:p/2).
              2. Set a trace pattern for the function(s) you want to trace using dbg:tp/2 @@ -102,16 +102,16 @@ values, and exceptions. [{'_',[],[{exception_trace}]}]
              3. c or caller_trace: Shows function names, parameters, and caller information. [{'_',[],[{message,{caller_line}}]}]
              4. cx or caller_exception_trace: Combines x and c. -[{'_',[],[{exception_trace},{message,{caller_line}}]}]

          Example using built-in aliases:

          1> dbg:tracer().
          -{ok,<0.90.0>}
          -2> dbg:p(all, c). % Short for dbg:p(all, call)
          -{ok,[{matched,nonode@nohost,49}]}
          -3> dbg:tp(lists, seq, cx). % cx: call and exception tracing with caller info
          -{ok,[{matched,nonode@nohost,2},{saved,cx}]}
          -4> lists:seq(1, 3).
          -(<0.88.0>) call lists:seq(1,3) ({erl_eval,do_apply,7,{"erl_eval.erl",904}})
          -[1,2,3]
          -(<0.88.0>) returned from lists:seq/2 -> [1,2,3]

          Note that the caller info is the function that called lists:seq with file and +[{'_',[],[{exception_trace},{message,{caller_line}}]}]

      Example using built-in aliases:

      1> dbg:tracer().
      +{ok,<0.90.0>}
      +2> dbg:p(all, c). % Short for dbg:p(all, call)
      +{ok,[{matched,nonode@nohost,49}]}
      +3> dbg:tp(lists, seq, cx). % cx: call and exception tracing with caller info
      +{ok,[{matched,nonode@nohost,2},{saved,cx}]}
      +4> lists:seq(1, 3).
      +(<0.88.0>) call lists:seq(1,3) ({erl_eval,do_apply,7,{"erl_eval.erl",904}})
      +[1,2,3]
      +(<0.88.0>) returned from lists:seq/2 -> [1,2,3]

      Note that the caller info is the function that called lists:seq with file and line number.

      Tracing Message Events (dbg:tpe/2)

      By default, if send or receive tracing is enabled for a process, all such events are traced. dbg:tpe(Event, MatchSpec) allows you to filter these events.

      • Event: send or 'receive'.
      • MatchSpec: A match specifications.
        • For send: Matches on [Receiver, Msg].
        • For 'receive': Matches on [Node, Sender, Msg].

      Managing Trace Patterns

      You can display, remove, save and load trace pattern matchspecifications, if @@ -135,10 +135,10 @@ enable it is by adding the following line to the source file: -include_lib("stdlib/include/ms_transform.hrl"). In the shell its already enabled.

      The head of the fun must be a single pattern that matches a list. That pattern -will be used to match the arguments for the call:

      1> dbg:fun2ms(fun([_,_]) -> true end). % Matches a function with two arguments
      -[{['_','_'],[],[true]}]
      -2> dbg:fun2ms(fun([A]) when is_atom(A) -> return_trace() end).
      -[{['$1'],[{is_atom,'$1'}],[{return_trace}]}]

      The first match specification matches when a function having two +will be used to match the arguments for the call:

      1> dbg:fun2ms(fun([_,_]) -> true end). % Matches a function with two arguments
      +[{['_','_'],[],[true]}]
      +2> dbg:fun2ms(fun([A]) when is_atom(A) -> return_trace() end).
      +[{['$1'],[{is_atom,'$1'}],[{return_trace}]}]

      The first match specification matches when a function having two arguments is called. The second matches when a function, taking one atom as an argument, is called.

      Trace Sessions

      To avoid interference between different tracing activities, you can create isolated dbg sessions.

      First you create a session with dbg:session_create(Name) @@ -147,37 +147,37 @@ This function runs dbg commands within Fun using the specified session.

      Any dbg function that is called with in the provided fun will use the session/0 provided instead of the default dbg session. This means that the tracing will be isolated -from other tracing users on the system.

      When you no longer need the session, use dbg:session_destroy(Session).

      Example:

      1> S = dbg:session_create(my_session).
      +from other tracing users on the system.

      When you no longer need the session, use dbg:session_destroy(Session).

      Example:

      1> S = dbg:session_create(my_session).
       <0.91.0>
      -2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(all,c), dbg:tp(lists,seq,x) end).
      -{ok,[{matched,nonode@nohost,2},{saved,x}]}
      -3> lists:seq(1, 10).
      -(<0.89.0>) call lists:seq(1,10)
      -(<0.89.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10]
      -[1,2,3,4,5,6,7,8,9,10]
      -4> dbg:session_destroy(S).
      +2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(all,c), dbg:tp(lists,seq,x) end).
      +{ok,[{matched,nonode@nohost,2},{saved,x}]}
      +3> lists:seq(1, 10).
      +(<0.89.0>) call lists:seq(1,10)
      +(<0.89.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10]
      +[1,2,3,4,5,6,7,8,9,10]
      +4> dbg:session_destroy(S).
       ok

      The state of the session/0 is preserved in between dbg:session/2 calls, so -you can call dbg:session/2 multiple times when debugging you application.

      Example:

      1> S = dbg:session_create(my_session).
      +you can call dbg:session/2 multiple times when debugging you application.

      Example:

      1> S = dbg:session_create(my_session).
       <0.91.0>
       %% Setup the initial traces
      -2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(self(),c), dbg:tp(lists,seq,x) end).
      -{ok,[{matched,nonode@nohost,2},{saved,x}]}
      -3> lists:seq(1, 3).
      -(<0.89.0>) call lists:seq(1,3)
      -(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
      -[1,2,3]
      +2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(self(),c), dbg:tp(lists,seq,x) end).
      +{ok,[{matched,nonode@nohost,2},{saved,x}]}
      +3> lists:seq(1, 3).
      +(<0.89.0>) call lists:seq(1,3)
      +(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
      +[1,2,3]
       %% Add an additional trace pattern
      -4> dbg:session(S, fun() -> dbg:tpl(lists,seq_loop,x) end).
      +4> dbg:session(S, fun() -> dbg:tpl(lists,seq_loop,x) end).
       ok
      -5> lists:seq(1, 3).
      -(<0.89.0>) call lists:seq(1,3)
      -(<0.89.0>) call lists:seq_loop(3,3,[])
      -(<0.89.0>) call lists:seq_loop(1,1,[2,3])
      -(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
      -(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
      -(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
      -[1,2,3]
      -6> dbg:session_destroy(S).
      +5> lists:seq(1, 3).
      +(<0.89.0>) call lists:seq(1,3)
      +(<0.89.0>) call lists:seq_loop(3,3,[])
      +(<0.89.0>) call lists:seq_loop(1,1,[2,3])
      +(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
      +(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
      +(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
      +[1,2,3]
      +6> dbg:session_destroy(S).
       ok

      Trace on Remote Nodes

      The dbg server keeps a list of nodes where tracing should be performed. Whenever a dbg:tp/2 call or a dbg:p/2 call is made, it is executed for all nodes in this list including the local node (except @@ -254,17 +254,17 @@ ignored.

      Example: Using an IP trace port and connecting to it from another node As an example, one can let trace messages be sent over the network to another Erlang node (preferably not distributed), where the formatting occurs.

      On the node stack there exists an Erlang node ant@stack. In the -shell, type the following:

      ant@stack> dbg:tracer(port, dbg:trace_port(ip, 4711)).
      +shell, type the following:

      ant@stack> dbg:tracer(port, dbg:trace_port(ip, 4711)).
       <0.17.0>
      -ant@stack> dbg:p(self(), send).
      -{ok,1}

      All trace messages are now sent to the trace port driver, which in turn listens +ant@stack> dbg:p(self(), send). +{ok,1}

      All trace messages are now sent to the trace port driver, which in turn listens for connections on the TCP/IP port 4711. If we want to see the messages on -another node, preferably on another host, we do like this:

      1> dbg:trace_client(ip, {"stack", 4711}).
      +another node, preferably on another host, we do like this:

      1> dbg:trace_client(ip, {"stack", 4711}).
       <0.42.0>

      If we now send a message from the shell on the node ant@stack, where all sends /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/dbg.xhtml differs (HTML document, ASCII text, with very long lines (494)) --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/dbg.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/dbg.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -1809,40 +1809,40 @@ as the argument of the function call; it cannot be held in a variable which in turn is passed to the function. Furthermore, the parse transform module ms_transform must be enabled. The easiest way to -enable it is by adding the following line to the source file:

      -include_lib("stdlib/include/ms_transform.hrl").

      Failing to include ms_transform.hrl in the source will result in a runtime +enable it is by adding the following line to the source file:

      -include_lib("stdlib/include/ms_transform.hrl").

      Failing to include ms_transform.hrl in the source will result in a runtime error, not a compile-time error.

      This function can also be invoked directly from the Erlang shell, as shown in the examples that follow.

      The head of the fun must be a single pattern that matches a list. That pattern -will be used to match the arguments for the call:

      Examples:

      1> dbg:fun2ms(fun([_,_]) -> true end).
      -[{['_','_'],[],[true]}]
      -2> dbg:fun2ms(fun(Args) when length(Args) > 6 -> true end).
      -[{'$1',[{'>',{length,'$1'},6}],[true]}]

      The first match specification matches when a function having two +will be used to match the arguments for the call:

      Examples:

      1> dbg:fun2ms(fun([_,_]) -> true end).
      +[{['_','_'],[],[true]}]
      +2> dbg:fun2ms(fun(Args) when length(Args) > 6 -> true end).
      +[{'$1',[{'>',{length,'$1'},6}],[true]}]

      The first match specification matches when a function having two arguments is called. The second matches when a function with more than -6 arguments is called.

      Examples:

      1> dbg:fun2ms(fun(42) -> true end).
      +6 arguments is called.

      Examples:

      1> dbg:fun2ms(fun(42) -> true end).
       Error: dbg:fun2ms requires fun with single variable or list parameter
      -{error,transform_error}
      -2> dbg:fun2ms(fun([<<H,T/binary>>]) -> true end).
      +{error,transform_error}
      +2> dbg:fun2ms(fun([<<H,T/binary>>]) -> true end).
       Error: fun head contains bit syntax matching of variable 'H', which cannot be translated into match_spec
      -{error,transform_error}

      The preceding two examples show what happens when a fun cannot be +{error,transform_error}

      The preceding two examples show what happens when a fun cannot be translated into a match specification. In the first example, the fun head connot possibly match a list. In the second example, an attempt is made to take apart a binary using the bit syntax, which is currently not -supported in match specifications.

      However, note that literal binaries can be matched:

      1> dbg:fun2ms(fun([<<"abc">>]) -> true end).
      -[{[<<"abc">>],[],[true]}]

      Match specifications support a large subset of the +supported in match specifications.

      However, note that literal binaries can be matched:

      1> dbg:fun2ms(fun([<<"abc">>]) -> true end).
      +[{[<<"abc">>],[],[true]}]

      Match specifications support a large subset of the guard expressions supported -by Erlang, but not all. For example, updating a map is currently not supported:

      1> dbg:fun2ms(fun([M]) when map_size(M#{a => b}) > 2 -> true end).
      -Error: the language element map (in guard) cannot be translated into match_spec
      -{error,transform_error}

      However, creating a map in a guard is allowed:

      1> dbg:fun2ms(fun([M]) when map_size(#{a => b}) > 2 -> true end).
      -[{['$1'],[{'>',{map_size,#{a => b}},2}],[true]}]

      Variables from the environment can be imported, so this works:

      1> X = 3.
      +by Erlang, but not all. For example, updating a map is currently not supported:

      1> dbg:fun2ms(fun([M]) when map_size(M#{a => b}) > 2 -> true end).
      +Error: the language element map (in guard) cannot be translated into match_spec
      +{error,transform_error}

      However, creating a map in a guard is allowed:

      1> dbg:fun2ms(fun([M]) when map_size(#{a => b}) > 2 -> true end).
      +[{['$1'],[{'>',{map_size,#{a => b}},2}],[true]}]

      Variables from the environment can be imported, so this works:

      1> X = 3.
       3
      -2> dbg:fun2ms(fun([M,N]) when N > X  -> return_trace() end).
      -[{['$1','$2'],[{'>','$2',{const,3}}],[{return_trace}]}]

      The imported variables will be replaced by const expressions, which +2> dbg:fun2ms(fun([M,N]) when N > X -> return_trace() end). +[{['$1','$2'],[{'>','$2',{const,3}}],[{return_trace}]}]

      The imported variables will be replaced by const expressions, which is consistent with the static scoping for Erlang funs.

      In the body of the fun, only guard expressions and calls to the special functions for tracing -are allowed.

      Examples:

      1> dbg:fun2ms(fun([A]) when is_atom(A) -> return_trace() end).
      -[{['$1'],[{is_atom,'$1'}],[{return_trace}]}]
      -2> dbg:fun2ms(fun(_) -> erlang:garbage_collect() end).
      -Error: fun containing the remote function call 'erlang:garbage_collect/0' (called in body) cannot be translated into match_spec
      -{error,transform_error}

      Warning

      If the parse transform is not applied to a module which calls dbg:fun2ms/1, +are allowed.

      Examples:

      1> dbg:fun2ms(fun([A]) when is_atom(A) -> return_trace() end).
      +[{['$1'],[{is_atom,'$1'}],[{return_trace}]}]
      +2> dbg:fun2ms(fun(_) -> erlang:garbage_collect() end).
      +Error: fun containing the remote function call 'erlang:garbage_collect/0' (called in body) cannot be translated into match_spec
      +{error,transform_error}

      Warning

      If the parse transform is not applied to a module which calls dbg:fun2ms/1, the call will fail in runtime with a badarg exception.

      More information is available in the documentation for module ms_transform in STDLIB.

      @@ -2050,16 +2050,16 @@ names, parameters, return values, and exceptions raised from functions

    • caller_trace, c - sets a trace that displays function names, parameters, and information about which function called it

    • caller_exception_trace, cx - combines exception_trace and -caller_trace

    Here is an example that shows how to use a built-in match specification:

    1> dbg:tracer().
    -{ok,<0.90.0>}
    -2> dbg:tp(lists, seq, 2, cx).
    -{ok,[{matched,nonode@nohost,1},{saved,cx}]}
    -3> dbg:p(self(), call).
    -{ok,[{matched,nonode@nohost,1}]}
    -4> lists:seq(1, 5).
    -(<0.88.0>) call lists:seq(1,5) ({erl_eval,do_apply,7,{"erl_eval.erl",904}})
    -[1,2,3,4,5]
    -(<0.88.0>) returned from lists:seq/2 -> [1,2,3,4,5]
    +caller_trace

    Here is an example that shows how to use a built-in match specification:

    1> dbg:tracer().
    +{ok,<0.90.0>}
    +2> dbg:tp(lists, seq, 2, cx).
    +{ok,[{matched,nonode@nohost,1},{saved,cx}]}
    +3> dbg:p(self(), call).
    +{ok,[{matched,nonode@nohost,1}]}
    +4> lists:seq(1, 5).
    +(<0.88.0>) call lists:seq(1,5) ({erl_eval,do_apply,7,{"erl_eval.erl",904}})
    +[1,2,3,4,5]
    +(<0.88.0>) returned from lists:seq/2 -> [1,2,3,4,5]
    @@ -2257,37 +2257,37 @@ is provided.

    Any dbg function that is called with in the provided fun will use the session/0 provided instead of the default dbg session. This means that the tracing will be isolated -from other tracing users on the system.

    The function returns the term that the fun returns.

    Example:

    1> S = dbg:session_create(my_session).
    +from other tracing users on the system.

    The function returns the term that the fun returns.

    Example:

    1> S = dbg:session_create(my_session).
     <0.91.0>
    -2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(all,c), dbg:tp(lists,seq,x) end).
    -{ok,[{matched,nonode@nohost,2},{saved,x}]}
    -3> lists:seq(1, 10).
    -(<0.89.0>) call lists:seq(1,10)
    -(<0.89.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10]
    -[1,2,3,4,5,6,7,8,9,10]
    -4> dbg:session_destroy(S).
    +2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(all,c), dbg:tp(lists,seq,x) end).
    +{ok,[{matched,nonode@nohost,2},{saved,x}]}
    +3> lists:seq(1, 10).
    +(<0.89.0>) call lists:seq(1,10)
    +(<0.89.0>) returned from lists:seq/2 -> [1,2,3,4,5,6,7,8,9,10]
    +[1,2,3,4,5,6,7,8,9,10]
    +4> dbg:session_destroy(S).
     ok

    The state of the session/0 is preserved in between session/2 calls, so -you can call session/2 multiple when debugging you application.

    Example:

    1> S = dbg:session_create(my_session).
    +you can call session/2 multiple when debugging you application.

    Example:

    1> S = dbg:session_create(my_session).
     <0.91.0>
     %% Setup the initial traces
    -2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(self(),c), dbg:tp(lists,seq,x) end).
    -{ok,[{matched,nonode@nohost,2},{saved,x}]}
    -3> lists:seq(1, 3).
    -(<0.89.0>) call lists:seq(1,3)
    -(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
    -[1,2,3]
    +2> dbg:session(S, fun() -> dbg:tracer(), dbg:p(self(),c), dbg:tp(lists,seq,x) end).
    +{ok,[{matched,nonode@nohost,2},{saved,x}]}
    +3> lists:seq(1, 3).
    +(<0.89.0>) call lists:seq(1,3)
    +(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
    +[1,2,3]
     %% Add an additional trace pattern
    -4> dbg:session(S, fun() -> dbg:tpl(lists,seq_loop,x) end).
    +4> dbg:session(S, fun() -> dbg:tpl(lists,seq_loop,x) end).
     ok
    -5> lists:seq(1, 3).
    -(<0.89.0>) call lists:seq(1,3)
    -(<0.89.0>) call lists:seq_loop(3,3,[])
    -(<0.89.0>) call lists:seq_loop(1,1,[2,3])
    -(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
    -(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
    -(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
    -[1,2,3]
    -6> dbg:session_destroy(S).
    +5> lists:seq(1, 3).
    +(<0.89.0>) call lists:seq(1,3)
    +(<0.89.0>) call lists:seq_loop(3,3,[])
    +(<0.89.0>) call lists:seq_loop(1,1,[2,3])
    +(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
    +(<0.89.0>) returned from lists:seq_loop/3 -> [1,2,3]
    +(<0.89.0>) returned from lists:seq/2 -> [1,2,3]
    +[1,2,3]
    +6> dbg:session_destroy(S).
     ok

    Note

    The session functionality is experimental in Erlang/OTP 27 and may change in future releases without notice.

    @@ -2461,11 +2461,11 @@ and will stand as an "alias" for the given expression.

    If the match specification is invalid, an {error, Errors} tuple is returned. Errors is as a list of tuples {error, string()}, where the string is a textual explanation of the compilation error. For -example:

    1> dbg:tp({dbg,ltp,0},[{[],[],[{message, two, arguments}, {noexist}]}]).
    -{error,
    - [{error,"Special form 'message' called with wrong number of
    -          arguments in {message,two,arguments}."},
    -  {error,"Function noexist/1 does_not_exist."}]}
    +example:

    1> dbg:tp({dbg,ltp,0},[{[],[],[{message, two, arguments}, {noexist}]}]).
    +{error,
    + [{error,"Special form 'message' called with wrong number of
    +          arguments in {message,two,arguments}."},
    +  {error,"Function noexist/1 does_not_exist."}]}
    @@ -2716,17 +2716,17 @@ host Hostname, from where it reads trace messages until the TCP/IP connection is closed. If no Hostname is specified, the local host is assumed.

    As an example, one can let trace messages be sent over the network to another Erlang node (preferably not distributed), where the formatting occurs.

    On the node stack there exists an Erlang node ant@stack. In the -shell, type the following:

    ant@stack> dbg:tracer(port, dbg:trace_port(ip, 4711)).
    +shell, type the following:

    ant@stack> dbg:tracer(port, dbg:trace_port(ip, 4711)).
     <0.17.0>
    -ant@stack> dbg:p(self(), send).
    -{ok,1}

    All trace messages are now sent to the trace port driver, which in turn listens +ant@stack> dbg:p(self(), send). +{ok,1}

    All trace messages are now sent to the trace port driver, which in turn listens for connections on the TCP/IP port 4711. If we want to see the messages on -another node, preferably on another host, we do like this:

    1> dbg:trace_client(ip, {"stack", 4711}).
    +another node, preferably on another host, we do like this:

    1> dbg:trace_client(ip, {"stack", 4711}).
     <0.42.0>

    If we now send a message from the shell on the node ant@stack, where all sends -from the shell are traced:

    ant@stack> self() ! hello.
    +from the shell are traced:

    ant@stack> self() ! hello.
     hello

    The following will appear at the console on the node that started the trace -client:

    (<0.23.0>) <0.23.0> ! hello
    -(<0.23.0>) <0.22.0> ! {shell_rep,<0.23.0>,{value,hello,[],[]}}

    The last line is generated due to internal message passing in the Erlang shell. +client:

    (<0.23.0>) <0.23.0> ! hello
    +(<0.23.0>) <0.22.0> ! {shell_rep,<0.23.0>,{value,hello,[],[]}}

    The last line is generated due to internal message passing in the Erlang shell. The pids will vary.

    @@ -2810,7 +2810,7 @@ /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/dyntrace.xhtml differs (HTML document, ASCII text, with very long lines (738)) --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/dyntrace.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/dyntrace.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -735,14 +735,14 @@

    Restores the previous state of user tags and their spreading as it was before a call to spread_tag/1.

    Note that the restoring is not limited to the same process; one can utilize this to turn off spreding in one process and restore it in a -newly created process that is is actually going to send messages:

    f() ->
    -    TagData = dyntrace:spread_tag(false),
    -    spawn(fun() ->
    -             dyntrace:restore_tag(TagData),
    -             do_something()
    -          end),
    -    do_something_else(),
    -    dyntrace:restore_tag(TagData).

    Correctly handling user tags and their spreading might take some effort, as +newly created process that is is actually going to send messages:

    f() ->
    +    TagData = dyntrace:spread_tag(false),
    +    spawn(fun() ->
    +             dyntrace:restore_tag(TagData),
    +             do_something()
    +          end),
    +    do_something_else(),
    +    dyntrace:restore_tag(TagData).

    Correctly handling user tags and their spreading might take some effort, as Erlang programs tend to send and receive messages so that sometimes the user tag gets lost due to various things, like double receives or communication with a port (ports do not handle user tags, in the same way as they do not handle @@ -789,12 +789,12 @@ later call to restore_tag/1.

    The file module already spreads tags, so there is no need to manually call this function to get user tags spread to the efile driver through that module.

    The most use of this function would be if one, for example, uses the io module to communicate with an I/O-server for a regular file, such as in the following -example:

    f() ->
    -   {ok, F} = file:open("test.tst", [write]),
    -   Saved = dyntrace:spread_tag(true),
    -   io:format(F, "Hello world!", []),
    -   dyntrace:restore_tag(Saved),
    -   file:close(F).

    In this example, any user tag set in the calling process will be spread to the +example:

    f() ->
    +   {ok, F} = file:open("test.tst", [write]),
    +   Saved = dyntrace:spread_tag(true),
    +   io:format(F, "Hello world!", []),
    +   dyntrace:restore_tag(Saved),
    +   file:close(F).

    In this example, any user tag set in the calling process will be spread to the I/O-server when the io:format/3 call is done.

    /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/instrument.xhtml differs (HTML document, ASCII text, with very long lines (1679)) --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/instrument.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/instrument.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -232,8 +232,8 @@ the one before it.

    The upper bound of the first interval is provided by the function that returned the histogram, and the last interval has no upper bound.

    For example, the histogram below has 40 (message) blocks between 128-256 bytes in size, 78 blocks between 256-512 bytes,2 blocks between 512-1024 bytes, and 2 -blocks between 1-2KB.

    > instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
    -{ok, {128, 0, #{ message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0}, ... } }}
    +blocks between 1-2KB.

    > instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
    +{ok, {128, 0, #{ message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0}, ... } }}
    @@ -368,30 +368,30 @@ block size histograms. Defaults to 128.

  • histogram_width - The number of intervals in the allocated block size histograms. Defaults to 18.

  • flags - Controls how to group the output, for example showing allocations on a per-process basis (when possible) rather than only a -NIF/driver-basis. Defaults to [].

  • Example:

    > instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
    -{ok,{128,0,
    -     #{udp_inet =>
    -           #{driver_event_state => {0,0,0,0,0,0,0,0,0,1,0,0,0,0,0}},
    +NIF/driver-basis. Defaults to [].

    Example:

    > instrument:allocations(#{ histogram_start => 128, histogram_width => 15 }).
    +{ok,{128,0,
    +     #{udp_inet =>
    +           #{driver_event_state => {0,0,0,0,0,0,0,0,0,1,0,0,0,0,0}},
            system =>
    -           #{heap => {0,0,0,0,20,4,2,2,2,3,0,1,0,0,1},
    -             db_term => {271,3,1,52,80,1,0,0,0,0,0,0,0,0,0},
    -             code => {0,0,0,5,3,6,11,22,19,20,10,2,1,0,0},
    -             binary => {18,0,0,0,7,0,0,1,0,0,0,0,0,0,0},
    -             message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0},
    -             ... }
    +           #{heap => {0,0,0,0,20,4,2,2,2,3,0,1,0,0,1},
    +             db_term => {271,3,1,52,80,1,0,0,0,0,0,0,0,0,0},
    +             code => {0,0,0,5,3,6,11,22,19,20,10,2,1,0,0},
    +             binary => {18,0,0,0,7,0,0,1,0,0,0,0,0,0,0},
    +             message => {0,40,78,2,2,0,0,0,0,0,0,0,0,0,0},
    +             ... }
            spawn_forker =>
    -           #{driver_select_data_state =>
    -                 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
    -       ram_file_drv => #{drv_binary => {0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}},
    +           #{driver_select_data_state =>
    +                 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
    +       ram_file_drv => #{drv_binary => {0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}},
            prim_file =>
    -           #{process_specific_data => {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    -             nif_trap_export_entry => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0},
    -             monitor_extended => {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
    -             drv_binary => {0,0,0,0,0,0,1,0,3,5,0,0,0,1,0},
    -             binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}},
    +           #{process_specific_data => {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    +             nif_trap_export_entry => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0},
    +             monitor_extended => {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
    +             drv_binary => {0,0,0,0,0,0,1,0,3,5,0,0,0,1,0},
    +             binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}},
            prim_buffer =>
    -           #{nif_internal => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0},
    -             binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}}
    +
    #{nif_internal => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}, + binary => {0,4,0,0,0,0,0,0,0,0,0,0,0,0,0}}}}}
    @@ -468,15 +468,15 @@ tied to any particular scheduler. Defaults to all schedulers and the global instance.

  • histogram_start - The upper bound of the first interval in the free block size histograms. Defaults to 512.

  • histogram_width - The number of intervals in the free block size -histograms. Defaults to 14.

  • Example:

    > instrument:carriers(#{ histogram_start => 512, histogram_width => 8 }).
    -{ok,{512,
    -     [{driver_alloc,false,262144,0,
    -                    [{driver_alloc,1,32784}],
    -                    {0,0,0,0,0,0,0,1}},
    -      {binary_alloc,false,32768,0,
    -                    [{binary_alloc,15,4304}],
    -                    {3,0,0,0,1,0,0,0}},
    -      {...}|...]}}
    +histograms. Defaults to 14.

    Example:

    > instrument:carriers(#{ histogram_start => 512, histogram_width => 8 }).
    +{ok,{512,
    +     [{driver_alloc,false,262144,0,
    +                    [{driver_alloc,1,32784}],
    +                    {0,0,0,0,0,0,0,1}},
    +      {binary_alloc,false,32768,0,
    +                    [{binary_alloc,15,4304}],
    +                    {3,0,0,0,1,0,0,0}},
    +      {...}|...]}}
    /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/lttng.xhtml differs (HTML document, ASCII text, with very long lines (21352)) --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/lttng.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/lttng.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -24,46 +24,46 @@ information on how to install LTTng on your system.

    After LTTng is properly installed on the system Erlang/OTP can be built with LTTng support.

    $ ./configure --with-dynamic-trace=lttng
     $ make

    Dyntrace Tracepoints

    All tracepoints are in the domain of org_erlang_dyntrace

    All Erlang types are the string equivalent in LTTng.

    process_spawn

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • parent : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"

    Available through erlang:trace/3 with trace flag procs and -{tracer,dyntrace,[]} as tracer module.

    Example:

    process_spawn: { cpu_id = 3 }, { pid = "<0.131.0>", parent = "<0.130.0>", entry = "erlang:apply/2" }

    process_link

    • to : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • from : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • type : string :: "link" | "unlink"

    Available through erlang:trace/3 with trace flag procs and +{tracer,dyntrace,[]} as tracer module.

    Example:

    process_spawn: { cpu_id = 3 }, { pid = "<0.131.0>", parent = "<0.130.0>", entry = "erlang:apply/2" }

    process_link

    • to : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • from : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • type : string :: "link" | "unlink"

    Available through erlang:trace/3 with trace flag procs and {tracer,dyntrace,[]} as tracer module.

    Example:

    process_link: { cpu_id = 3 }, { from = "<0.130.0>", to = "<0.131.0>", type = "link" }

    process_exit

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • reason : string :: Exit reason. Ex. "normal"

    Available through erlang:trace/3 with trace flag procs and -{tracer,dyntrace,[]} as tracer module.

    Example:

    process_exit: { cpu_id = 3 }, { pid = "<0.130.0>", reason = "normal" }

    process_register

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • name : string :: Registered name. Ex. "logger"
    • type : string :: "register" | "unregister"

    Example:

    process_register: { cpu_id = 0 }, { pid = "<0.128.0>", name = "dyntrace_lttng_SUITE" type = "register" }

    process_scheduled

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"
    • type : string :: +{tracer,dyntrace,[]} as tracer module.

      Example:

      process_exit: { cpu_id = 3 }, { pid = "<0.130.0>", reason = "normal" }

      process_register

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • name : string :: Registered name. Ex. "logger"
      • type : string :: "register" | "unregister"

      Example:

      process_register: { cpu_id = 0 }, { pid = "<0.128.0>", name = "dyntrace_lttng_SUITE" type = "register" }

      process_scheduled

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • entry : string :: Code Location. Ex. "lists:sort/1"
      • type : string :: "in" | "out" | "in_exiting" | "out_exiting" | "out_exited"

      Available through erlang:trace/3 with trace flag running and -{tracer,dyntrace,[]} as tracer module.

      Example:

      process_scheduled: { cpu_id = 0 }, { pid = "<0.136.0>", entry = "erlang:apply/2", type = "in" }

      port_open

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • port : string :: Port ID. Ex. "#Port<0.1031>"

      Available through erlang:trace/3 with trace flag ports and +{tracer,dyntrace,[]} as tracer module.

      Example:

      process_scheduled: { cpu_id = 0 }, { pid = "<0.136.0>", entry = "erlang:apply/2", type = "in" }

      port_open

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • port : string :: Port ID. Ex. "#Port<0.1031>"

      Available through erlang:trace/3 with trace flag ports and {tracer,dyntrace,[]} as tracer module.

      Example:

      port_open: { cpu_id = 5 }, { pid = "<0.131.0>", driver = "'/bin/sh -s unix:cmd'", port = "#Port<0.1887>" }

      port_exit

      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • reason : string :: Exit reason. Ex. "normal"

      Available through erlang:trace/3 with trace flag ports and {tracer,dyntrace,[]} as tracer module.

      Example:

      port_exit: { cpu_id = 5 }, { port = "#Port<0.1887>", reason = "normal" }

      port_link

      • to : string :: Process ID. Ex. "<0.131.0>"
      • from : string :: Process ID. Ex. "<0.131.0>"
      • type : string :: "link" | "unlink"

      Available through erlang:trace/3 with trace flag ports and -{tracer,dyntrace,[]} as tracer module.

      Example:

      port_link: { cpu_id = 5 }, { from = "#Port<0.1887>", to = "<0.131.0>", type = "unlink" }

      port_scheduled

      Available through erlang:trace/3 with trace flag running and +{tracer,dyntrace,[]} as tracer module.

      Example:

      port_link: { cpu_id = 5 }, { from = "#Port<0.1887>", to = "<0.131.0>", type = "unlink" }

      port_scheduled

      Available through erlang:trace/3 with trace flag running and {tracer,dyntrace,[]} as tracer module.

      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • entry : string :: Callback. Ex. "open"
      • type : string :: -"in" | "out" | "in_exiting" | "out_exiting" | "out_exited"

      Example:

      port_scheduled: { cpu_id = 5 }, { pid = "#Port<0.1905>", entry = "close", type = "out" }

      Available through erlang:trace/3 with trace flag running and +"in" | "out" | "in_exiting" | "out_exiting" | "out_exited"

    Example:

    port_scheduled: { cpu_id = 5 }, { pid = "#Port<0.1905>", entry = "close", type = "out" }

    Available through erlang:trace/3 with trace flag running and {tracer,dyntrace,[]} as tracer module.

    function_call

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"
    • depth : integer :: Stack depth. Ex. 0

    Available through erlang:trace/3 with trace flag call and -{tracer,dyntrace,[]} as tracer module.

    Example:

    function_call: { cpu_id = 5 }, { pid = "<0.145.0>", entry = "dyntrace_lttng_SUITE:'-t_call/1-fun-1-'/0", depth = 0 }

    function_return

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"
    • depth : integer :: Stack depth. Ex. 0

    Available through erlang:trace/3 with trace flag call or return_to and -{tracer,dyntrace,[]} as tracer module.

    Example:

    function_return: { cpu_id = 5 }, { pid = "<0.145.0>", entry = "dyntrace_lttng_SUITE:waiter/0", depth = 0 }

    function_exception

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"
    • class : string :: Error reason. Ex. "error"

    Available through erlang:trace/3 with trace flag call and -{tracer,dyntrace,[]} as tracer module.

    Example:

    function_exception: { cpu_id = 5 }, { pid = "<0.144.0>", entry = "t:call_exc/1", class = "error" }

    message_send

    • from : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • to : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • message : string :: Message sent. Ex. "{<0.162.0>,ok}"

    Available through erlang:trace/3 with trace flag send and +{tracer,dyntrace,[]} as tracer module.

    Example:

    function_call: { cpu_id = 5 }, { pid = "<0.145.0>", entry = "dyntrace_lttng_SUITE:'-t_call/1-fun-1-'/0", depth = 0 }

    function_return

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"
    • depth : integer :: Stack depth. Ex. 0

    Available through erlang:trace/3 with trace flag call or return_to and +{tracer,dyntrace,[]} as tracer module.

    Example:

    function_return: { cpu_id = 5 }, { pid = "<0.145.0>", entry = "dyntrace_lttng_SUITE:waiter/0", depth = 0 }

    function_exception

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • entry : string :: Code Location. Ex. "lists:sort/1"
    • class : string :: Error reason. Ex. "error"

    Available through erlang:trace/3 with trace flag call and +{tracer,dyntrace,[]} as tracer module.

    Example:

    function_exception: { cpu_id = 5 }, { pid = "<0.144.0>", entry = "t:call_exc/1", class = "error" }

    message_send

    • from : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • to : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • message : string :: Message sent. Ex. "{<0.162.0>,ok}"

    Available through erlang:trace/3 with trace flag send and {tracer,dyntrace,[]} as tracer module.

    Example:

    message_send: { cpu_id = 3 }, { from = "#Port<0.1938>", to = "<0.160.0>", message = "{#Port<0.1938>,eof}" }

    message_receive

    • to : string :: Process ID or Port ID. Ex. "<0.131.0>"
    • message : string :: Message received. Ex. "{<0.162.0>,ok}"

    Available through erlang:trace/3 with trace flag 'receive' and {tracer,dyntrace,[]} as tracer module.

    Example:

    message_receive: { cpu_id = 7 }, { to = "<0.167.0>", message = "{<0.165.0>,ok}" }

    gc_minor_start

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • need : integer :: Heap need. Ex. 2
    • heap : integer :: Young heap word size. Ex. 233
    • old_heap : integer :: Old heap word size. Ex. 233

    Available through erlang:trace/3 with trace flag garbage_collection and -{tracer,dyntrace,[]} as tracer module.

    Example:

    gc_minor_start: { cpu_id = 0 }, { pid = "<0.172.0>", need = 0, heap = 610, old_heap = 0 }

    gc_minor_end

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • reclaimed : integer :: Heap reclaimed. Ex. 2
    • heap : integer :: Young heap word size. Ex. 233
    • old_heap : integer :: Old heap word size. Ex. 233

    Available through erlang:trace/3 with trace flag garbage_collection and -{tracer,dyntrace,[]} as tracer module.

    Example:

    gc_minor_end: { cpu_id = 0 }, { pid = "<0.172.0>", reclaimed = 120, heap = 1598, old_heap = 1598 }

    gc_major_start

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • need : integer :: Heap need. Ex. 2
    • heap : integer :: Young heap word size. Ex. 233
    • old_heap : integer :: Old heap word size. Ex. 233

    Available through erlang:trace/3 with trace flag garbage_collection and -{tracer,dyntrace,[]} as tracer module.

    Example:

    gc_major_start: { cpu_id = 0 }, { pid = "<0.172.0>", need = 8, heap = 2586, old_heap = 1598 }

    gc_major_end

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • reclaimed : integer :: Heap reclaimed. Ex. 2
    • heap : integer :: Young heap word size. Ex. 233
    • old_heap : integer :: Old heap word size. Ex. 233

    Available through erlang:trace/3 with trace flag garbage_collection and -{tracer,dyntrace,[]} as tracer module.

    Example:

    gc_major_end: { cpu_id = 0 }, { pid = "<0.172.0>", reclaimed = 240, heap = 4185, old_heap = 0 }

    BEAM Tracepoints

    All tracepoints are in the domain of org_erlang_otp

    All Erlang types are the string equivalent in LTTng.

    driver_init

    • driver : string :: Driver name. Ex. "tcp_inet"
    • major : integer :: Major version. Ex. 3
    • minor : integer :: Minor version. Ex. 1
    • flags : integer :: Flags. Ex. 1

    Example:

    driver_init: { cpu_id = 2 }, { driver = "caller_drv", major = 3, minor = 3, flags = 1 }

    driver_start

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • driver : string :: Driver name. Ex. "tcp_inet"
    • port : string :: Port ID. Ex. "#Port<0.1031>"

    Example:

    driver_start: { cpu_id = 2 }, { pid = "<0.198.0>", driver = "caller_drv", port = "#Port<0.3676>" }

    driver_output

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"
    • bytes : integer :: Size of data returned. Ex. 82

    Example:

    driver_output: { cpu_id = 2 }, { pid = "<0.198.0>", port = "#Port<0.3677>", driver = "/bin/sh -s unix:cmd", bytes = 36 }

    driver_outputv

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"
    • bytes : integer :: Size of data returned. Ex. 82

    Example:

    driver_outputv: { cpu_id = 5 }, { pid = "<0.194.0>", port = "#Port<0.3663>", driver = "tcp_inet", bytes = 3 }

    driver_ready_input

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_ready_input: { cpu_id = 5 }, { pid = "<0.189.0>", port = "#Port<0.3637>", driver = "inet_gethost 4 " }

    driver_ready_output

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_ready_output: { cpu_id = 5 }, { pid = "<0.194.0>", port = "#Port<0.3663>", driver = "tcp_inet" }

    driver_timeout

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_timeout: { cpu_id = 5 }, { pid = "<0.196.0>", port = "#Port<0.3664>", driver = "tcp_inet" }

    driver_stop_select

    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_stop_select: { cpu_id = 5 }, { driver = "unknown" }

    driver_flush

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_flush: { cpu_id = 7 }, { pid = "<0.204.0>", port = "#Port<0.3686>", driver = "tcp_inet" }

    driver_stop

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_stop: { cpu_id = 5 }, { pid = "[]", port = "#Port<0.3673>", driver = "tcp_inet" }

    driver_process_exit

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    driver_ready_async

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"

    Example:

    driver_ready_async: { cpu_id = 3 }, { pid = "<0.181.0>", port = "#Port<0.3622>", driver = "tcp_inet" }

    driver_call

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"
    • command : integer :: Command integer. Ex. 1
    • bytes : integer :: Size of data returned. Ex. 82

    Example:

    driver_call: { cpu_id = 2 }, { pid = "<0.202.0>", port = "#Port<0.3676>", driver = "caller_drv", command = 0, bytes = 2 }

    driver_control

    • pid : string :: Process ID. Ex. "<0.131.0>"
    • port : string :: Port ID. Ex. "#Port<0.1031>"
    • driver : string :: Driver name. Ex. "tcp_inet"
    • command : integer :: Command integer. Ex. 1
    • bytes : integer :: Size of data returned. Ex. 82

    Example:

    driver_control: { cpu_id = 3 }, { pid = "<0.32767.8191>", port = "#Port<0.0>", driver = "forker", command = 83, bytes = 32 }

    carrier_create

    • type : string :: Carrier type. Ex. "ets_alloc"
    • instance : integer :: Allocator instance. Ex. 1
    • size : integer :: Carrier size. Ex. 262144
    • mbc_carriers : integer :: Number of multiblock carriers in instance. Ex. 3
    • mbc_carriers_size : integer :: Total size of multiblock blocks carriers in +{tracer,dyntrace,[]} as tracer module.

      Example:

      gc_minor_start: { cpu_id = 0 }, { pid = "<0.172.0>", need = 0, heap = 610, old_heap = 0 }

      gc_minor_end

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • reclaimed : integer :: Heap reclaimed. Ex. 2
      • heap : integer :: Young heap word size. Ex. 233
      • old_heap : integer :: Old heap word size. Ex. 233

      Available through erlang:trace/3 with trace flag garbage_collection and +{tracer,dyntrace,[]} as tracer module.

      Example:

      gc_minor_end: { cpu_id = 0 }, { pid = "<0.172.0>", reclaimed = 120, heap = 1598, old_heap = 1598 }

      gc_major_start

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • need : integer :: Heap need. Ex. 2
      • heap : integer :: Young heap word size. Ex. 233
      • old_heap : integer :: Old heap word size. Ex. 233

      Available through erlang:trace/3 with trace flag garbage_collection and +{tracer,dyntrace,[]} as tracer module.

      Example:

      gc_major_start: { cpu_id = 0 }, { pid = "<0.172.0>", need = 8, heap = 2586, old_heap = 1598 }

      gc_major_end

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • reclaimed : integer :: Heap reclaimed. Ex. 2
      • heap : integer :: Young heap word size. Ex. 233
      • old_heap : integer :: Old heap word size. Ex. 233

      Available through erlang:trace/3 with trace flag garbage_collection and +{tracer,dyntrace,[]} as tracer module.

      Example:

      gc_major_end: { cpu_id = 0 }, { pid = "<0.172.0>", reclaimed = 240, heap = 4185, old_heap = 0 }

      BEAM Tracepoints

      All tracepoints are in the domain of org_erlang_otp

      All Erlang types are the string equivalent in LTTng.

      driver_init

      • driver : string :: Driver name. Ex. "tcp_inet"
      • major : integer :: Major version. Ex. 3
      • minor : integer :: Minor version. Ex. 1
      • flags : integer :: Flags. Ex. 1

      Example:

      driver_init: { cpu_id = 2 }, { driver = "caller_drv", major = 3, minor = 3, flags = 1 }

      driver_start

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • port : string :: Port ID. Ex. "#Port<0.1031>"

      Example:

      driver_start: { cpu_id = 2 }, { pid = "<0.198.0>", driver = "caller_drv", port = "#Port<0.3676>" }

      driver_output

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • bytes : integer :: Size of data returned. Ex. 82

      Example:

      driver_output: { cpu_id = 2 }, { pid = "<0.198.0>", port = "#Port<0.3677>", driver = "/bin/sh -s unix:cmd", bytes = 36 }

      driver_outputv

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • bytes : integer :: Size of data returned. Ex. 82

      Example:

      driver_outputv: { cpu_id = 5 }, { pid = "<0.194.0>", port = "#Port<0.3663>", driver = "tcp_inet", bytes = 3 }

      driver_ready_input

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_ready_input: { cpu_id = 5 }, { pid = "<0.189.0>", port = "#Port<0.3637>", driver = "inet_gethost 4 " }

      driver_ready_output

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_ready_output: { cpu_id = 5 }, { pid = "<0.194.0>", port = "#Port<0.3663>", driver = "tcp_inet" }

      driver_timeout

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_timeout: { cpu_id = 5 }, { pid = "<0.196.0>", port = "#Port<0.3664>", driver = "tcp_inet" }

      driver_stop_select

      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_stop_select: { cpu_id = 5 }, { driver = "unknown" }

      driver_flush

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_flush: { cpu_id = 7 }, { pid = "<0.204.0>", port = "#Port<0.3686>", driver = "tcp_inet" }

      driver_stop

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_stop: { cpu_id = 5 }, { pid = "[]", port = "#Port<0.3673>", driver = "tcp_inet" }

      driver_process_exit

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      driver_ready_async

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"

      Example:

      driver_ready_async: { cpu_id = 3 }, { pid = "<0.181.0>", port = "#Port<0.3622>", driver = "tcp_inet" }

      driver_call

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • command : integer :: Command integer. Ex. 1
      • bytes : integer :: Size of data returned. Ex. 82

      Example:

      driver_call: { cpu_id = 2 }, { pid = "<0.202.0>", port = "#Port<0.3676>", driver = "caller_drv", command = 0, bytes = 2 }

      driver_control

      • pid : string :: Process ID. Ex. "<0.131.0>"
      • port : string :: Port ID. Ex. "#Port<0.1031>"
      • driver : string :: Driver name. Ex. "tcp_inet"
      • command : integer :: Command integer. Ex. 1
      • bytes : integer :: Size of data returned. Ex. 82

      Example:

      driver_control: { cpu_id = 3 }, { pid = "<0.32767.8191>", port = "#Port<0.0>", driver = "forker", command = 83, bytes = 32 }

      carrier_create

      • type : string :: Carrier type. Ex. "ets_alloc"
      • instance : integer :: Allocator instance. Ex. 1
      • size : integer :: Carrier size. Ex. 262144
      • mbc_carriers : integer :: Number of multiblock carriers in instance. Ex. 3
      • mbc_carriers_size : integer :: Total size of multiblock blocks carriers in instance. Ex. 1343488
      • mbc_blocks : integer :: Number of multiblock blocks in instance. Ex. 122
      • mbc_blocks_size : integer :: Total size of all multiblock blocks in instance. Ex. 285296
      • sbc_carriers : integer :: Number of singleblock carriers in instance. Ex. 1
      • sbc_carriers_size : integer :: Total size of singleblock blocks carriers in instance. Ex. 1343488
      • sbc_blocks : integer :: Number of singleblocks in instance. Ex. 1
      • sbc_blocks_size : integer :: Total size of all singleblock blocks in -instance. Ex. 285296

      Example:

      carrier_create: { cpu_id = 2 }, { type = "ets_alloc", instance = 7, size = 2097152, mbc_carriers = 4, mbc_carriers_size = 3440640, mbc_blocks = 526, mbc_blocks_size = 1278576, sbc_carriers = 0, sbc_carriers_size = 0, sbc_blocks = 0, sbc_blocks_size = 0 }

      carrier_destroy

      • type : string :: Carrier type. Ex. "ets_alloc"
      • instance : integer :: Allocator instance. Ex. 1
      • size : integer :: Carrier size. Ex. 262144
      • mbc_carriers : integer :: Number of multiblock carriers in instance. Ex. 3
      • mbc_carriers_size : integer :: Total size of multiblock blocks carriers in +instance. Ex. 285296

      Example:

      carrier_create: { cpu_id = 2 }, { type = "ets_alloc", instance = 7, size = 2097152, mbc_carriers = 4, mbc_carriers_size = 3440640, mbc_blocks = 526, mbc_blocks_size = 1278576, sbc_carriers = 0, sbc_carriers_size = 0, sbc_blocks = 0, sbc_blocks_size = 0 }

      carrier_destroy

      • type : string :: Carrier type. Ex. "ets_alloc"
      • instance : integer :: Allocator instance. Ex. 1
      • size : integer :: Carrier size. Ex. 262144
      • mbc_carriers : integer :: Number of multiblock carriers in instance. Ex. 3
      • mbc_carriers_size : integer :: Total size of multiblock blocks carriers in instance. Ex. 1343488
      • mbc_blocks : integer :: Number of multiblock blocks in instance. Ex. 122
      • mbc_blocks_size : integer :: Total size of all multiblock blocks in instance. Ex. 285296
      • sbc_carriers : integer :: Number of singleblock carriers in instance. Ex. 1
      • sbc_carriers_size : integer :: Total size of singleblock blocks carriers in instance. Ex. 1343488
      • sbc_blocks : integer :: Number of singleblocks in instance. Ex. 1
      • sbc_blocks_size : integer :: Total size of all singleblock blocks in -instance. Ex. 285296

      Example:

      carrier_destroy: { cpu_id = 6 }, { type = "ets_alloc", instance = 7, size = 262144, mbc_carriers = 3, mbc_carriers_size = 3178496, mbc_blocks = 925, mbc_blocks_size = 2305336, sbc_carriers = 0, sbc_carriers_size = 0, sbc_blocks = 0, sbc_blocks_size = 0 }

      carrier_pool_put

      • type : string :: Carrier type. Ex. "ets_alloc"
      • instance : integer :: Allocator instance. Ex. 1
      • size : integer :: Carrier size. Ex. 262144

      Example:

      carrier_pool_put: { cpu_id = 3 }, { type = "ets_alloc", instance = 5, size = 1048576 }

      carrier_pool_get

      • type : string :: Carrier type. Ex. "ets_alloc"
      • instance : integer :: Allocator instance. Ex. 1
      • size : integer :: Carrier size. Ex. 262144

      Example:

      carrier_pool_get: { cpu_id = 7 }, { type = "ets_alloc", instance = 4, size = 3208 }

      Example of process tracing

      An example of process tracing of os_mon and friends.

      Clean start of lttng in a bash shell.

      $ lttng create erlang-demo
      +instance. Ex. 285296

    Example:

    carrier_destroy: { cpu_id = 6 }, { type = "ets_alloc", instance = 7, size = 262144, mbc_carriers = 3, mbc_carriers_size = 3178496, mbc_blocks = 925, mbc_blocks_size = 2305336, sbc_carriers = 0, sbc_carriers_size = 0, sbc_blocks = 0, sbc_blocks_size = 0 }

    carrier_pool_put

    • type : string :: Carrier type. Ex. "ets_alloc"
    • instance : integer :: Allocator instance. Ex. 1
    • size : integer :: Carrier size. Ex. 262144

    Example:

    carrier_pool_put: { cpu_id = 3 }, { type = "ets_alloc", instance = 5, size = 1048576 }

    carrier_pool_get

    • type : string :: Carrier type. Ex. "ets_alloc"
    • instance : integer :: Allocator instance. Ex. 1
    • size : integer :: Carrier size. Ex. 262144

    Example:

    carrier_pool_get: { cpu_id = 7 }, { type = "ets_alloc", instance = 4, size = 3208 }

    Example of process tracing

    An example of process tracing of os_mon and friends.

    Clean start of lttng in a bash shell.

    $ lttng create erlang-demo
     Spawning a session daemon
     Session erlang-demo created.
     Traces will be written in /home/egil/lttng-traces/erlang-demo-20160526-165920

    Start an Erlang node with lttng enabled.

    $ erl
     Erlang/OTP 19 [erts-8.0] [source-4d7b24d] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [lttng]
     
     Eshell V8.0  (abort with ^G)
    -1>

    Load the dyntrace module.

    1> l(dyntrace).
    -{module,dyntrace}

    All tracepoints via dyntrace are now visible and can be listed through +1>

    Load the dyntrace module.

    1> l(dyntrace).
    +{module,dyntrace}

    All tracepoints via dyntrace are now visible and can be listed through lttng list -u.

    Enable the process_register LTTng tracepoint for Erlang.

    $ lttng enable-event -u org_erlang_dyntrace:process_register
    -UST event org_erlang_dyntrace:process_register created in channel channel0

    Enable process tracing for new processes and use dyntrace as tracer backend.

    2> erlang:trace(new,true,[procs,{tracer,dyntrace,[]}]).
    +UST event org_erlang_dyntrace:process_register created in channel channel0

    Enable process tracing for new processes and use dyntrace as tracer backend.

    2> erlang:trace(new,true,[procs,{tracer,dyntrace,[]}]).
     0

    Start LTTng tracing.

    $ lttng start
     Tracing started for session erlang-demo

    Start the os_mon application in Erlang.

    3> application:ensure_all_started(os_mon).
     {ok,[sasl,os_mon]}

    Stop LTTng tracing and view the result.

    $ lttng stop
    /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/msacc.xhtml differs (HTML document, ASCII text, with very long lines (1991))
    --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/msacc.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/msacc.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -25,9 +25,9 @@
     

    Convenience functions for microstate accounting

    This module implements some convenience functions for analyzing microstate accounting data. For details about how to use the basic API and what the different states represent, see -erlang:statistics(microstate_accounting).

    Basic Scenario

    1> msacc:start(1000).
    +erlang:statistics(microstate_accounting).

    Basic Scenario

    1> msacc:start(1000).
     ok
    -2> msacc:print().
    +2> msacc:print().
     Average thread real-time    : 1000513 us
     Accumulated system run-time :    2213 us
     Average scheduler run-time  :    1076 us
    @@ -35,11 +35,11 @@
             Thread      aux check_io emulator       gc    other     port    sleep
     
     Stats per thread:
    -     async( 0)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
    -     async( 1)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
    -       aux( 1)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%   99.99%
    - scheduler( 1)    0.00%    0.03%    0.13%    0.00%    0.01%    0.00%   99.82%
    - scheduler( 2)    0.00%    0.00%    0.00%    0.00%    0.03%    0.00%   99.97%
    +     async( 0)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
    +     async( 1)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
    +       aux( 1)    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%   99.99%
    + scheduler( 1)    0.00%    0.03%    0.13%    0.00%    0.01%    0.00%   99.82%
    + scheduler( 2)    0.00%    0.00%    0.00%    0.00%    0.03%    0.00%   99.97%
     
     Stats per type:
              async    0.00%    0.00%    0.00%    0.00%    0.00%    0.00%  100.00%
    @@ -823,7 +823,7 @@
     this can be verbose. See the top of this reference manual for a brief
     description of what the fields mean.

    It is possible to print more specific types of statistics by first manipulating the DataOrStats using stats/2. For instance if you want to print the -percentage of run-time for each thread you can do:

    msacc:print(msacc:stats(runtime, msacc:stats())).

    If you want to only print run-time per thread type you can do:

    msacc:print(msacc:stats(type, msacc:stats(runtime, msacc:stats()))).

    Options

    • system - Print percentage of time spent in each state out of system time +percentage of run-time for each thread you can do:

      msacc:print(msacc:stats(runtime, msacc:stats())).

      If you want to only print run-time per thread type you can do:

      msacc:print(msacc:stats(type, msacc:stats(runtime, msacc:stats()))).

      Options

      • system - Print percentage of time spent in each state out of system time as well as thread time. Default: false.
      /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/notes.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (4972)) --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -17,9 +17,9 @@

      Runtime_Tools Release Notes

      -

      This document describes the changes made to the Runtime_Tools application.

      Runtime_Tools 2.3.1

      Improvements and New Features

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      Runtime_Tools 2.3

      Fixed Bugs and Malfunctions

      • NIFs and linked-in drivers are now loadable when running in an Erlang source tree on Windows.

        Own Id: OTP-19686 Aux Id: PR-9969

      Improvements and New Features

      • The default tracer is now aware that it is started by a remote shell (-remsh), in which case the traces will be sent to the remote group_leader to make the traces visible in the remote shell.

        Own Id: OTP-19648 Aux Id: PR-9589

      • A User's Guide to dbg is now available in the documentation.

        Own Id: OTP-19655 Aux Id: PR-9853

      Runtime_Tools 2.2

      Improvements and New Features

      • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

        All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

        -type meter() :: integer().
        --type foot() :: integer().

        Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

        -nominal meter() :: integer().
        --nominal foot() :: integer().

        More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

        Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

        Own Id: OTP-19364 Aux Id: PR-9079

      • When compiling C/C++ code on Unix systems, the compiler hardening flags suggested by the Open Source Security Foundation are now enabled by default. To disable them, pass --disable-security-hardening-flags to configure.

        Own Id: OTP-19519 Aux Id: PR-9441

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      • With this change observer will use cheaper iterators to avoid locking when not necessary.

        Own Id: OTP-19584 Aux Id: PR-9711

      Runtime_Tools 2.1.1

      Fixed Bugs and Malfunctions

      • Fixed a bug where dbg sessions on remote nodes were terminated prematurely.

        Own Id: OTP-19188 Aux Id: PR-8692

      Runtime_Tools 2.1

      Improvements and New Features

      • The instrument module can now track allocations on a per-process or per-port basis.

        Own Id: OTP-18577 Aux Id: PR-7236

      • The new function proc_lib:set_label/1 can be used to add a descriptive term to any process that does not have a registered name. The name will be shown by tools such as c:i/0, observer, and it will be included in crash reports produced by processes using gen_server, gen_statem, gen_event, and gen_fsm.

        The label for a process can be retrieved by calling proc_lib:get_label/1.

        Note that those functions work on any process, not only processes that use proc_lib.

        Example:

        1> self().
        +

        This document describes the changes made to the Runtime_Tools application.

        Runtime_Tools 2.3.1

        Improvements and New Features

        • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

          A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

          make release_docs places the documentation in the released code under the doc folder.

          make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

          The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

          Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

          Improves the source Software-Bill-of-Materials

          • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
          • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
          • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

          Own Id: OTP-19886 Aux Id: PR-10434

        Runtime_Tools 2.3

        Fixed Bugs and Malfunctions

        • NIFs and linked-in drivers are now loadable when running in an Erlang source tree on Windows.

          Own Id: OTP-19686 Aux Id: PR-9969

        Improvements and New Features

        • The default tracer is now aware that it is started by a remote shell (-remsh), in which case the traces will be sent to the remote group_leader to make the traces visible in the remote shell.

          Own Id: OTP-19648 Aux Id: PR-9589

        • A User's Guide to dbg is now available in the documentation.

          Own Id: OTP-19655 Aux Id: PR-9853

        Runtime_Tools 2.2

        Improvements and New Features

        • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

          All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

          -type meter() :: integer().
          +-type foot() :: integer().

          Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

          -nominal meter() :: integer().
          +-nominal foot() :: integer().

          More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

          Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

          Own Id: OTP-19364 Aux Id: PR-9079

        • When compiling C/C++ code on Unix systems, the compiler hardening flags suggested by the Open Source Security Foundation are now enabled by default. To disable them, pass --disable-security-hardening-flags to configure.

          Own Id: OTP-19519 Aux Id: PR-9441

        • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

          Own Id: OTP-19575 Aux Id: PR-9670

        • With this change observer will use cheaper iterators to avoid locking when not necessary.

          Own Id: OTP-19584 Aux Id: PR-9711

        Runtime_Tools 2.1.1

        Fixed Bugs and Malfunctions

        • Fixed a bug where dbg sessions on remote nodes were terminated prematurely.

          Own Id: OTP-19188 Aux Id: PR-8692

        Runtime_Tools 2.1

        Improvements and New Features

        • The instrument module can now track allocations on a per-process or per-port basis.

          Own Id: OTP-18577 Aux Id: PR-7236

        • The new function proc_lib:set_label/1 can be used to add a descriptive term to any process that does not have a registered name. The name will be shown by tools such as c:i/0, observer, and it will be included in crash reports produced by processes using gen_server, gen_statem, gen_event, and gen_fsm.

          The label for a process can be retrieved by calling proc_lib:get_label/1.

          Note that those functions work on any process, not only processes that use proc_lib.

          Example:

          1> self().
           <0.90.0>
           2> proc_lib:set_label(my_label).
           ok
          /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/scheduler.xhtml differs (HTML document, ASCII text, with very long lines (669))
          --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/scheduler.xhtml	2026-08-05 05:56:49.000000000 +0000
          +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/runtime_tools.epub/OEBPS/scheduler.xhtml	2026-08-05 05:56:49.000000000 +0000
          @@ -491,7 +491,7 @@
           scheduler_wall_time.

          Calculate scheduler utilizations for the time interval from when Sample was taken and "now". The same as calling scheduler:utilization(Sample, scheduler:sample_all()).

          Note

          This function is not recommended as it's so easy to get invalid results -without noticing. In particular do not do this:

          scheduler:utilization(scheduler:sample()). % DO NOT DO THIS!

          The above example takes two samples in rapid succession and calculates the +without noticing. In particular do not do this:

          scheduler:utilization(scheduler:sample()). % DO NOT DO THIS!

          The above example takes two samples in rapid succession and calculates the scheduler utilization between them. The resulting values will probably be more misleading than informative.

          Instead use scheduler:utilization/2 and call get_sample/0 to get samples with some time in between.

          /usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/scheduler.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/scheduler.html 2026-08-21 04:00:26.823342932 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/runtime_tools-2.3.1/doc/html/scheduler.html 2026-08-21 04:00:26.823342932 +0000 @@ -578,7 +578,7 @@ scheduler_wall_time.

          Calculate scheduler utilizations for the time interval from when Sample was taken and "now". The same as calling scheduler:utilization(Sample, scheduler:sample_all()).

          Note

          This function is not recommended as it's so easy to get invalid results -without noticing. In particular do not do this:

          scheduler:utilization(scheduler:sample()). % DO NOT DO THIS!

          The above example takes two samples in rapid succession and calculates the +without noticing. In particular do not do this:

          scheduler:utilization(scheduler:sample()). % DO NOT DO THIS!

          The above example takes two samples in rapid succession and calculates the scheduler utilization between them. The resulting values will probably be more misleading than informative.

          Instead use scheduler:utilization/2 and call get_sample/0 to get samples with some time in between.

          /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/appup.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (854)) --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/appup.html 2026-08-21 04:00:26.844343069 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/appup.html 2026-08-21 04:00:26.844343069 +0000 @@ -95,9 +95,9 @@ Application is the application name. The file is to be located in the ebin directory for the application.

          The .appup file contains one single Erlang term, which defines the instructions used to upgrade or downgrade the application. The file has the -following syntax:

          {Vsn,
          -  [{UpFromVsn, Instructions}, ...],
          -  [{DownToVsn, Instructions}, ...]}.
          • Vsn = string() - Current application version.

          • UpFromVsn = string() | binary() - An earlier application version to +following syntax:

            {Vsn,
            +  [{UpFromVsn, Instructions}, ...],
            +  [{DownToVsn, Instructions}, ...]}.
            • Vsn = string() - Current application version.

            • UpFromVsn = string() | binary() - An earlier application version to upgrade from. If it is a string, it is interpreted as a specific version number. If it is a binary, it is interpreted as a regular expression that can match multiple version numbers.

            • DownToVsn = string() | binary() - An earlier application version to @@ -160,21 +160,21 @@ version. For static modules, the new version is loaded before the process is asked to change code, both in the case of upgrading and downgrading. Callback modules are dynamic.

            update with argument supervisor is used when changing the start -specification of a supervisor.

            {load_module, Mod}
            -{load_module, Mod, DepMods}
            -{load_module, Mod, PrePurge, PostPurge, DepMods}
            -  Mod = atom()
            +specification of a supervisor.

            {load_module, Mod}
            +{load_module, Mod, DepMods}
            +{load_module, Mod, PrePurge, PostPurge, DepMods}
            +  Mod = atom()
               PrePurge = PostPurge = soft_purge | brutal_purge
            -  DepMods = [Mod]

            Simple code replacement of the module Mod.

            For a description of PrePurge and PostPurge, see update above.

            DepMods defaults to [] and defines which other modules Mod is dependent + DepMods = [Mod]

            Simple code replacement of the module Mod.

            For a description of PrePurge and PostPurge, see update above.

            DepMods defaults to [] and defines which other modules Mod is dependent on. In the relup file, instructions for loading these modules come before the -instruction for loading Mod when upgrading, and conversely when downgrading.

            {add_module, Mod}
            -{add_module, Mod, DepMods}
            -  Mod = atom()
            -  DepMods = [Mod]

            Loads a new module Mod.

            DepMods defaults to [] and defines which other modules Mod is dependent +instruction for loading Mod when upgrading, and conversely when downgrading.

            {add_module, Mod}
            +{add_module, Mod, DepMods}
            +  Mod = atom()
            +  DepMods = [Mod]

            Loads a new module Mod.

            DepMods defaults to [] and defines which other modules Mod is dependent on. In the relup file, instructions related to these modules come before the -instruction for loading Mod when upgrading, and conversely when downgrading.

            {delete_module, Mod}
            -{delete_module, Mod, DepMods}
            -  Mod = atom()

            Deletes a module Mod using the low-level instructions remove and purge.

            DepMods defaults to [] and defines which other modules Mod is dependent +instruction for loading Mod when upgrading, and conversely when downgrading.

            {delete_module, Mod}
            +{delete_module, Mod, DepMods}
            +  Mod = atom()

            Deletes a module Mod using the low-level instructions remove and purge.

            DepMods defaults to [] and defines which other modules Mod is dependent on. In the relup file, instructions related to these modules come before the instruction for removing Mod when upgrading, and conversely when downgrading.

            {add_application, Application}
             {add_application, Application, Type}
            @@ -195,9 +195,9 @@
             load it rather than start it, depending on the application's start type:
             If Type = load, the application is only loaded. If Type = none, the
             application is not loaded and not started, although the code for its modules is
            -loaded.

            Low-Level Instructions

            {load_object_code, {App, Vsn, [Mod]}}
            -  App = Mod = atom()
            -  Vsn = string()

            Reads each Mod from directory App-Vsn/ebin as a binary. It does not load the +loaded.

            Low-Level Instructions

            {load_object_code, {App, Vsn, [Mod]}}
            +  App = Mod = atom()
            +  Vsn = string()

            Reads each Mod from directory App-Vsn/ebin as a binary. It does not load the modules. The instruction is to be placed first in the script to read all new code from the file to make the suspend-load-resume cycle less time-consuming.

            point_of_no_return

            If a crash occurs after this instruction, the system cannot recover and is restarted from the old release version. The instruction must only occur once in @@ -211,38 +211,38 @@ PrePurge = PostPurge = soft_purge | brutal_purge

            Makes the current version of Mod old. PrePurge is ignored. For a description of PostPurge, see the high-level instruction update earlier.

            {purge, [Mod]}
               Mod = atom()

            Purges each module Mod, that is, removes the old code. Notice that any process -executing purged code is killed.

            {suspend, [Mod | {Mod, Timeout}]}
            -  Mod = atom()
            -  Timeout = int()>0 | default | infinity

            Tries to suspend all processes using a module Mod. If a process does not +executing purged code is killed.

            {suspend, [Mod | {Mod, Timeout}]}
            +  Mod = atom()
            +  Timeout = int()>0 | default | infinity

            Tries to suspend all processes using a module Mod. If a process does not respond, it is ignored. This can cause the process to die, either because it crashes when it spontaneously switches to new code, or as a result of a purge operation. If no Timeout is specified or default is specified, the default value for sys:suspend is used.

            {resume, [Mod]}
            -  Mod = atom()

            Resumes all suspended processes using a module Mod.

            {code_change, [{Mod, Extra}]}
            -{code_change, Mode, [{Mod, Extra}]}
            -  Mod = atom()
            +  Mod = atom()

            Resumes all suspended processes using a module Mod.

            {code_change, [{Mod, Extra}]}
            +{code_change, Mode, [{Mod, Extra}]}
            +  Mod = atom()
               Mode = up | down
            -  Extra = term()

            Mode defaults to up and specifies if it is an upgrade or downgrade. This + Extra = term()

          Mode defaults to up and specifies if it is an upgrade or downgrade. This instruction sends a code_change system message to all processes using a module Mod by calling function sys:change_code, passing term Extra as argument.

          {stop, [Mod]}
             Mod = atom()

          Stops all processes using a module Mod by calling supervisor:terminate_child/2. This instruction is useful when the simplest way -to change code is to stop and restart the processes that run the code.

          {start, [Mod]}
          -  Mod = atom()

          Starts all stopped processes using a module Mod by calling -supervisor:restart_child/2.

          {sync_nodes, Id, [Node]}
          -{sync_nodes, Id, {M, F, A}}
          -  Id = term()
          -  Node = node()
          -  M = F = atom()
          -  A = [term()]

          apply(M, F, A) must return a list of nodes.

          This instruction synchronizes the release installation with other nodes. Each +to change code is to stop and restart the processes that run the code.

          {start, [Mod]}
          +  Mod = atom()

          Starts all stopped processes using a module Mod by calling +supervisor:restart_child/2.

          {sync_nodes, Id, [Node]}
          +{sync_nodes, Id, {M, F, A}}
          +  Id = term()
          +  Node = node()
          +  M = F = atom()
          +  A = [term()]

          apply(M, F, A) must return a list of nodes.

          This instruction synchronizes the release installation with other nodes. Each Node must evaluate this command with the same Id. The local node waits for all other nodes to evaluate the instruction before execution continues. If a node goes down, it is considered to be an unrecoverable error, and the local node is restarted from the old release. There is no time-out for this -instruction, which means that it can hang forever.

          {apply, {M, F, A}}
          -  M = F = atom()
          -  A = [term()]

          Evaluates apply(M, F, A).

          If the instruction appears before instruction point_of_no_return, a failure is +instruction, which means that it can hang forever.

          {apply, {M, F, A}}
          +  M = F = atom()
          +  A = [term()]

          Evaluates apply(M, F, A).

          If the instruction appears before instruction point_of_no_return, a failure is caught. release_handler:install_release/1 then returns {error,{'EXIT',Reason}}, unless {error,Error} is thrown or returned. Then it returns {error,Error}.

          If the instruction appears after instruction point_of_no_return and the /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/error_logging.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1022)) --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/error_logging.html 2026-08-21 04:00:26.867343218 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/error_logging.html 2026-08-21 04:00:26.868343225 +0000 @@ -206,42 +206,42 @@ 2 error <0.15.0> 1996-10-16 16:17:04 1 progress <0.14.0> 1996-10-16 16:17:09 ok

        Show Reports

        Use function rb:show(Number) to show details of a specific -report:

        7> rb:show(4).
        +report:

        7> rb:show(4).
         
         PROGRESS REPORT  <0.20.0>                                   1996-10-16 16:16:36
         ===============================================================================
        -supervisor                                                     {local,sasl_sup}
        +supervisor                                                     {local,sasl_sup}
         started
        -[{pid,<0.24.0>},
        -{name,release_handler},
        -{mfa,{release_handler,start_link,[]}},
        -{restart_type,permanent},
        -{shutdown,2000},
        -{child_type,worker}]
        +[{pid,<0.24.0>},
        +{name,release_handler},
        +{mfa,{release_handler,start_link,[]}},
        +{restart_type,permanent},
        +{shutdown,2000},
        +{child_type,worker}]
         
         ok
        -8> rb:show(9).
        +8> rb:show(9).
         
         CRASH REPORT  <0.24.0>                                      1996-10-16 16:16:21
         ===============================================================================
         Crashing process
         pid                                                                 <0.24.0>
         registered_name                                              release_handler
        -error_info                             {undef,{release_handler,mbj_func,[]}}
        +error_info                             {undef,{release_handler,mbj_func,[]}}
         initial_call
        -{gen,init_it,
        -[gen_server,
        +{gen,init_it,
        +[gen_server,
         <0.20.0>,
         <0.20.0>,
        -{erlang,register},
        +{erlang,register},
         release_handler,
         release_handler,
        -[],
        -[]]}
        -ancestors                                                [sasl_sup,<0.18.0>]
        -messages                                                                  []
        -links                                                    [<0.23.0>,<0.20.0>]
        -dictionary                                                                []
        +[],
        +[]]}
        +ancestors                                                [sasl_sup,<0.18.0>]
        +messages                                                                  []
        +links                                                    [<0.23.0>,<0.20.0>]
        +dictionary                                                                []
         trap_exit                                                              false
         status                                                               running
         heap_size                                                                610
        /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/rel.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1220))
        --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/rel.html	2026-08-21 04:00:26.887343349 +0000
        +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/rel.html	2026-08-21 04:00:26.887343349 +0000
        @@ -92,11 +92,11 @@
         

        Release resource file

        Description

        The release resource file specifies which applications are included in a release (system) based on Erlang/OTP.

        This file is used by the functions in systools when generating start scripts (.script, .boot) and release upgrade files (relup).

        File Syntax

        The release resource file is to be called Name.rel.

        The .rel file contains one single Erlang term, which is called a release -specification. The file has the following syntax:

        {release, {RelName,Vsn}, {erts, EVsn},
        -  [{Application, AppVsn} |
        -   {Application, AppVsn, Type} |
        -   {Application, AppVsn, IncApps} |
        -   {Application, AppVsn, Type, IncApps}]}.
        • RelName = string() - Release name.

        • Vsn = string() - Release version.

        • EVsn = string() - ERTS version the release is intended for.

        • Application = atom() - Name of an application included in the release.

        • AppVsn = string() - Version of an application included in the release.

        • Type = permanent | transient | temporary | load | none - Start type of +specification. The file has the following syntax:

          {release, {RelName,Vsn}, {erts, EVsn},
          +  [{Application, AppVsn} |
          +   {Application, AppVsn, Type} |
          +   {Application, AppVsn, IncApps} |
          +   {Application, AppVsn, Type, IncApps}]}.
          • RelName = string() - Release name.

          • Vsn = string() - Release version.

          • EVsn = string() - ERTS version the release is intended for.

          • Application = atom() - Name of an application included in the release.

          • AppVsn = string() - Version of an application included in the release.

          • Type = permanent | transient | temporary | load | none - Start type of an application included in the release.

            If Type = permanent | transient | temporary, the application is loaded and started in the corresponding way, see application.

            If Type = load, the application is only loaded.

            If Type = none, the application is not loaded and not started, although the code for its modules is loaded.

            Defaults to permanent

          • IncApps = [atom()] - A list of applications that are included by an /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/release_handler.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (854)) --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/release_handler.html 2026-08-21 04:00:26.915343531 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/release_handler.html 2026-08-21 04:00:26.915343531 +0000 @@ -1031,8 +1031,8 @@ create_RELEASES/4 or set_unpacked/2.

            Example:

            In the current version CurVsn of a release, the application directory of myapp is $ROOT/lib/myapp-1.0. A new version NewVsn is unpacked outside the release handler and the release handler is informed about this with a call -as follows:

            release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
            -=> {ok,NewVsn}

            If NewVsn is installed with option {update_paths,true}, then +as follows:

            release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
            +=> {ok,NewVsn}

            If NewVsn is installed with option {update_paths,true}, then code:lib_dir(myapp) returns /home/user/myapp-1.0.

          Note

          Installing a new release can be time consuming if there are many processes in the system. The reason is that each process must be checked for references to old code before a module can be purged. This check can lead to garbage /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/relup.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (980)) --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/relup.html 2026-08-21 04:00:26.935343661 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/relup.html 2026-08-21 04:00:26.935343661 +0000 @@ -95,9 +95,9 @@ file (.rel), application resource files (.app), and application upgrade files (.appup) as input.

          File Syntax

          In a target system, the release upgrade file is to be located in directory $ROOT/releases/Vsn.

          The relup file contains one single Erlang term, which defines the instructions -used to upgrade the release. The file has the following syntax:

          {Vsn,
          -  [{UpFromVsn, Descr, Instructions}, ...],
          -  [{DownToVsn, Descr, Instructions}, ...]}.
          • Vsn = string() - Current release version.

          • UpFromVsn = string() - Earlier version of the release to upgrade from.

          • Descr = term() - A user-defined parameter passed from the function +used to upgrade the release. The file has the following syntax:

            {Vsn,
            +  [{UpFromVsn, Descr, Instructions}, ...],
            +  [{DownToVsn, Descr, Instructions}, ...]}.
            • Vsn = string() - Current release version.

            • UpFromVsn = string() - Earlier version of the release to upgrade from.

            • Descr = term() - A user-defined parameter passed from the function systools:make_relup/3,4. It is used in the return value of release_handler:install_release/1,2.

            • Instructions - A list of low-level release upgrade instructions, see /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/appup.xhtml differs (HTML document, ASCII text, with very long lines (777)) --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/appup.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/appup.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -23,9 +23,9 @@ Application is the application name. The file is to be located in the ebin directory for the application.

              The .appup file contains one single Erlang term, which defines the instructions used to upgrade or downgrade the application. The file has the -following syntax:

              {Vsn,
              -  [{UpFromVsn, Instructions}, ...],
              -  [{DownToVsn, Instructions}, ...]}.
              • Vsn = string() - Current application version.

              • UpFromVsn = string() | binary() - An earlier application version to +following syntax:

                {Vsn,
                +  [{UpFromVsn, Instructions}, ...],
                +  [{DownToVsn, Instructions}, ...]}.
                • Vsn = string() - Current application version.

                • UpFromVsn = string() | binary() - An earlier application version to upgrade from. If it is a string, it is interpreted as a specific version number. If it is a binary, it is interpreted as a regular expression that can match multiple version numbers.

                • DownToVsn = string() | binary() - An earlier application version to @@ -88,21 +88,21 @@ version. For static modules, the new version is loaded before the process is asked to change code, both in the case of upgrading and downgrading. Callback modules are dynamic.

                update with argument supervisor is used when changing the start -specification of a supervisor.

                {load_module, Mod}
                -{load_module, Mod, DepMods}
                -{load_module, Mod, PrePurge, PostPurge, DepMods}
                -  Mod = atom()
                +specification of a supervisor.

                {load_module, Mod}
                +{load_module, Mod, DepMods}
                +{load_module, Mod, PrePurge, PostPurge, DepMods}
                +  Mod = atom()
                   PrePurge = PostPurge = soft_purge | brutal_purge
                -  DepMods = [Mod]

                Simple code replacement of the module Mod.

                For a description of PrePurge and PostPurge, see update above.

                DepMods defaults to [] and defines which other modules Mod is dependent + DepMods = [Mod]

                Simple code replacement of the module Mod.

                For a description of PrePurge and PostPurge, see update above.

                DepMods defaults to [] and defines which other modules Mod is dependent on. In the relup file, instructions for loading these modules come before the -instruction for loading Mod when upgrading, and conversely when downgrading.

                {add_module, Mod}
                -{add_module, Mod, DepMods}
                -  Mod = atom()
                -  DepMods = [Mod]

                Loads a new module Mod.

                DepMods defaults to [] and defines which other modules Mod is dependent +instruction for loading Mod when upgrading, and conversely when downgrading.

                {add_module, Mod}
                +{add_module, Mod, DepMods}
                +  Mod = atom()
                +  DepMods = [Mod]

                Loads a new module Mod.

                DepMods defaults to [] and defines which other modules Mod is dependent on. In the relup file, instructions related to these modules come before the -instruction for loading Mod when upgrading, and conversely when downgrading.

                {delete_module, Mod}
                -{delete_module, Mod, DepMods}
                -  Mod = atom()

                Deletes a module Mod using the low-level instructions remove and purge.

                DepMods defaults to [] and defines which other modules Mod is dependent +instruction for loading Mod when upgrading, and conversely when downgrading.

                {delete_module, Mod}
                +{delete_module, Mod, DepMods}
                +  Mod = atom()

                Deletes a module Mod using the low-level instructions remove and purge.

                DepMods defaults to [] and defines which other modules Mod is dependent on. In the relup file, instructions related to these modules come before the instruction for removing Mod when upgrading, and conversely when downgrading.

                {add_application, Application}
                 {add_application, Application, Type}
                @@ -123,9 +123,9 @@
                 load it rather than start it, depending on the application's start type:
                 If Type = load, the application is only loaded. If Type = none, the
                 application is not loaded and not started, although the code for its modules is
                -loaded.

                Low-Level Instructions

                {load_object_code, {App, Vsn, [Mod]}}
                -  App = Mod = atom()
                -  Vsn = string()

                Reads each Mod from directory App-Vsn/ebin as a binary. It does not load the +loaded.

                Low-Level Instructions

                {load_object_code, {App, Vsn, [Mod]}}
                +  App = Mod = atom()
                +  Vsn = string()

                Reads each Mod from directory App-Vsn/ebin as a binary. It does not load the modules. The instruction is to be placed first in the script to read all new code from the file to make the suspend-load-resume cycle less time-consuming.

                point_of_no_return

                If a crash occurs after this instruction, the system cannot recover and is restarted from the old release version. The instruction must only occur once in @@ -139,38 +139,38 @@ PrePurge = PostPurge = soft_purge | brutal_purge

                Makes the current version of Mod old. PrePurge is ignored. For a description of PostPurge, see the high-level instruction update earlier.

                {purge, [Mod]}
                   Mod = atom()

                Purges each module Mod, that is, removes the old code. Notice that any process -executing purged code is killed.

                {suspend, [Mod | {Mod, Timeout}]}
                -  Mod = atom()
                -  Timeout = int()>0 | default | infinity

                Tries to suspend all processes using a module Mod. If a process does not +executing purged code is killed.

                {suspend, [Mod | {Mod, Timeout}]}
                +  Mod = atom()
                +  Timeout = int()>0 | default | infinity

                Tries to suspend all processes using a module Mod. If a process does not respond, it is ignored. This can cause the process to die, either because it crashes when it spontaneously switches to new code, or as a result of a purge operation. If no Timeout is specified or default is specified, the default value for sys:suspend is used.

                {resume, [Mod]}
                -  Mod = atom()

                Resumes all suspended processes using a module Mod.

                {code_change, [{Mod, Extra}]}
                -{code_change, Mode, [{Mod, Extra}]}
                -  Mod = atom()
                +  Mod = atom()

                Resumes all suspended processes using a module Mod.

                {code_change, [{Mod, Extra}]}
                +{code_change, Mode, [{Mod, Extra}]}
                +  Mod = atom()
                   Mode = up | down
                -  Extra = term()

                Mode defaults to up and specifies if it is an upgrade or downgrade. This + Extra = term()

        Mode defaults to up and specifies if it is an upgrade or downgrade. This instruction sends a code_change system message to all processes using a module Mod by calling function sys:change_code, passing term Extra as argument.

        {stop, [Mod]}
           Mod = atom()

        Stops all processes using a module Mod by calling supervisor:terminate_child/2. This instruction is useful when the simplest way -to change code is to stop and restart the processes that run the code.

        {start, [Mod]}
        -  Mod = atom()

        Starts all stopped processes using a module Mod by calling -supervisor:restart_child/2.

        {sync_nodes, Id, [Node]}
        -{sync_nodes, Id, {M, F, A}}
        -  Id = term()
        -  Node = node()
        -  M = F = atom()
        -  A = [term()]

        apply(M, F, A) must return a list of nodes.

        This instruction synchronizes the release installation with other nodes. Each +to change code is to stop and restart the processes that run the code.

        {start, [Mod]}
        +  Mod = atom()

        Starts all stopped processes using a module Mod by calling +supervisor:restart_child/2.

        {sync_nodes, Id, [Node]}
        +{sync_nodes, Id, {M, F, A}}
        +  Id = term()
        +  Node = node()
        +  M = F = atom()
        +  A = [term()]

        apply(M, F, A) must return a list of nodes.

        This instruction synchronizes the release installation with other nodes. Each Node must evaluate this command with the same Id. The local node waits for all other nodes to evaluate the instruction before execution continues. If a node goes down, it is considered to be an unrecoverable error, and the local node is restarted from the old release. There is no time-out for this -instruction, which means that it can hang forever.

        {apply, {M, F, A}}
        -  M = F = atom()
        -  A = [term()]

        Evaluates apply(M, F, A).

        If the instruction appears before instruction point_of_no_return, a failure is +instruction, which means that it can hang forever.

        {apply, {M, F, A}}
        +  M = F = atom()
        +  A = [term()]

        Evaluates apply(M, F, A).

        If the instruction appears before instruction point_of_no_return, a failure is caught. release_handler:install_release/1 then returns {error,{'EXIT',Reason}}, unless {error,Error} is thrown or returned. Then it returns {error,Error}.

        If the instruction appears after instruction point_of_no_return and the /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> sasl - 4.3.2 - urn:uuid:1b4f21e0-ae78-ca90-4473-1e7619a93a45 + urn:uuid:ff53bfbc-9071-6e46-7e2e-2428bd925a58 en - 2026-08-21T03:47:25Z + 2042-09-22T17:06:01Z /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/error_logging.xhtml differs (HTML document, ASCII text, with very long lines (1022)) --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/error_logging.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/error_logging.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -134,42 +134,42 @@ 2 error <0.15.0> 1996-10-16 16:17:04 1 progress <0.14.0> 1996-10-16 16:17:09 ok

        Show Reports

        Use function rb:show(Number) to show details of a specific -report:

        7> rb:show(4).
        +report:

        7> rb:show(4).
         
         PROGRESS REPORT  <0.20.0>                                   1996-10-16 16:16:36
         ===============================================================================
        -supervisor                                                     {local,sasl_sup}
        +supervisor                                                     {local,sasl_sup}
         started
        -[{pid,<0.24.0>},
        -{name,release_handler},
        -{mfa,{release_handler,start_link,[]}},
        -{restart_type,permanent},
        -{shutdown,2000},
        -{child_type,worker}]
        +[{pid,<0.24.0>},
        +{name,release_handler},
        +{mfa,{release_handler,start_link,[]}},
        +{restart_type,permanent},
        +{shutdown,2000},
        +{child_type,worker}]
         
         ok
        -8> rb:show(9).
        +8> rb:show(9).
         
         CRASH REPORT  <0.24.0>                                      1996-10-16 16:16:21
         ===============================================================================
         Crashing process
         pid                                                                 <0.24.0>
         registered_name                                              release_handler
        -error_info                             {undef,{release_handler,mbj_func,[]}}
        +error_info                             {undef,{release_handler,mbj_func,[]}}
         initial_call
        -{gen,init_it,
        -[gen_server,
        +{gen,init_it,
        +[gen_server,
         <0.20.0>,
         <0.20.0>,
        -{erlang,register},
        +{erlang,register},
         release_handler,
         release_handler,
        -[],
        -[]]}
        -ancestors                                                [sasl_sup,<0.18.0>]
        -messages                                                                  []
        -links                                                    [<0.23.0>,<0.20.0>]
        -dictionary                                                                []
        +[],
        +[]]}
        +ancestors                                                [sasl_sup,<0.18.0>]
        +messages                                                                  []
        +links                                                    [<0.23.0>,<0.20.0>]
        +dictionary                                                                []
         trap_exit                                                              false
         status                                                               running
         heap_size                                                                610
        /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/release_handler.xhtml differs (HTML document, ASCII text, with very long lines (854))
        --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/release_handler.xhtml	2026-08-05 05:56:49.000000000 +0000
        +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/release_handler.xhtml	2026-08-05 05:56:49.000000000 +0000
        @@ -944,8 +944,8 @@
         create_RELEASES/4 or set_unpacked/2.

        Example:

        In the current version CurVsn of a release, the application directory of myapp is $ROOT/lib/myapp-1.0. A new version NewVsn is unpacked outside the release handler and the release handler is informed about this with a call -as follows:

        release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
        -=> {ok,NewVsn}

        If NewVsn is installed with option {update_paths,true}, then +as follows:

        release_handler:set_unpacked(RelFile, [{myapp,"1.0","/home/user"},...]).
        +=> {ok,NewVsn}

        If NewVsn is installed with option {update_paths,true}, then code:lib_dir(myapp) returns /home/user/myapp-1.0.

      Note

      Installing a new release can be time consuming if there are many processes in the system. The reason is that each process must be checked for references to old code before a module can be purged. This check can lead to garbage /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/relup.xhtml differs (HTML document, ASCII text, with very long lines (980)) --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/relup.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/relup.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -23,9 +23,9 @@ file (.rel), application resource files (.app), and application upgrade files (.appup) as input.

      File Syntax

      In a target system, the release upgrade file is to be located in directory $ROOT/releases/Vsn.

      The relup file contains one single Erlang term, which defines the instructions -used to upgrade the release. The file has the following syntax:

      {Vsn,
      -  [{UpFromVsn, Descr, Instructions}, ...],
      -  [{DownToVsn, Descr, Instructions}, ...]}.
      • Vsn = string() - Current release version.

      • UpFromVsn = string() - Earlier version of the release to upgrade from.

      • Descr = term() - A user-defined parameter passed from the function +used to upgrade the release. The file has the following syntax:

        {Vsn,
        +  [{UpFromVsn, Descr, Instructions}, ...],
        +  [{DownToVsn, Descr, Instructions}, ...]}.
        • Vsn = string() - Current release version.

        • UpFromVsn = string() - Earlier version of the release to upgrade from.

        • Descr = term() - A user-defined parameter passed from the function systools:make_relup/3,4. It is used in the return value of release_handler:install_release/1,2.

        • Instructions - A list of low-level release upgrade instructions, see /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/rel.xhtml differs (HTML document, ASCII text, with very long lines (1220)) --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/rel.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/rel.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -20,11 +20,11 @@

          Release resource file

          Description

          The release resource file specifies which applications are included in a release (system) based on Erlang/OTP.

          This file is used by the functions in systools when generating start scripts (.script, .boot) and release upgrade files (relup).

          File Syntax

          The release resource file is to be called Name.rel.

          The .rel file contains one single Erlang term, which is called a release -specification. The file has the following syntax:

          {release, {RelName,Vsn}, {erts, EVsn},
          -  [{Application, AppVsn} |
          -   {Application, AppVsn, Type} |
          -   {Application, AppVsn, IncApps} |
          -   {Application, AppVsn, Type, IncApps}]}.
          • RelName = string() - Release name.

          • Vsn = string() - Release version.

          • EVsn = string() - ERTS version the release is intended for.

          • Application = atom() - Name of an application included in the release.

          • AppVsn = string() - Version of an application included in the release.

          • Type = permanent | transient | temporary | load | none - Start type of +specification. The file has the following syntax:

            {release, {RelName,Vsn}, {erts, EVsn},
            +  [{Application, AppVsn} |
            +   {Application, AppVsn, Type} |
            +   {Application, AppVsn, IncApps} |
            +   {Application, AppVsn, Type, IncApps}]}.
            • RelName = string() - Release name.

            • Vsn = string() - Release version.

            • EVsn = string() - ERTS version the release is intended for.

            • Application = atom() - Name of an application included in the release.

            • AppVsn = string() - Version of an application included in the release.

            • Type = permanent | transient | temporary | load | none - Start type of an application included in the release.

              If Type = permanent | transient | temporary, the application is loaded and started in the corresponding way, see application.

              If Type = load, the application is only loaded.

              If Type = none, the application is not loaded and not started, although the code for its modules is loaded.

              Defaults to permanent

            • IncApps = [atom()] - A list of applications that are included by an /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/script.xhtml differs (HTML document, ASCII text, with very long lines (714)) --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/script.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/sasl.epub/OEBPS/script.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -22,20 +22,20 @@ to start.

              Command erl -boot Name starts the system with a boot file called Name.boot, which is generated from the Name.script file, using systools:script2boot/1.

              The .script file is generated by systools from a .rel file and from .app files.

              File Syntax

              The boot script is stored in a file with extension .script. The file has the -following syntax:

              {script, {Name, Vsn},
              - [
              -  {progress, loading},
              -  {preLoaded, [Mod1, Mod2, ...]},
              -  {path, [Dir1,"$ROOT/Dir",...]}.
              -  {primLoad, [Mod1, Mod2, ...]},
              +following syntax:

              {script, {Name, Vsn},
              + [
              +  {progress, loading},
              +  {preLoaded, [Mod1, Mod2, ...]},
              +  {path, [Dir1,"$ROOT/Dir",...]}.
              +  {primLoad, [Mod1, Mod2, ...]},
                 ...
              -  {kernel_load_completed},
              -  {progress, loaded},
              -  {kernelProcess, Name, {Mod, Func, Args}},
              +  {kernel_load_completed},
              +  {progress, loaded},
              +  {kernelProcess, Name, {Mod, Func, Args}},
                 ...
              -  {apply, {Mod, Func, Args}},
              +  {apply, {Mod, Func, Args}},
                 ...
              -  {progress, started}]}.
              • Name = string() - Defines the system name.

              • Vsn = string() - Defines the system version.

              • {progress, Term} - Sets the "progress" of the initialization program. + {progress, started}]}.

              • Name = string() - Defines the system name.

              • Vsn = string() - Defines the system version.

              • {progress, Term} - Sets the "progress" of the initialization program. The init:get_status/0 function returns the current value of the progress, which is {InternalStatus,Term}.

              • {path, [Dir]} - Dir is a string. This argument sets the load path of the system to [Dir]. The load path used to load modules is obtained from the /usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/script.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/script.html 2026-08-21 04:00:27.070344540 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/sasl-4.3.2/doc/html/script.html 2026-08-21 04:00:27.070344540 +0000 @@ -94,20 +94,20 @@ to start.

                Command erl -boot Name starts the system with a boot file called Name.boot, which is generated from the Name.script file, using systools:script2boot/1.

                The .script file is generated by systools from a .rel file and from .app files.

                File Syntax

                The boot script is stored in a file with extension .script. The file has the -following syntax:

                {script, {Name, Vsn},
                - [
                -  {progress, loading},
                -  {preLoaded, [Mod1, Mod2, ...]},
                -  {path, [Dir1,"$ROOT/Dir",...]}.
                -  {primLoad, [Mod1, Mod2, ...]},
                +following syntax:

                {script, {Name, Vsn},
                + [
                +  {progress, loading},
                +  {preLoaded, [Mod1, Mod2, ...]},
                +  {path, [Dir1,"$ROOT/Dir",...]}.
                +  {primLoad, [Mod1, Mod2, ...]},
                   ...
                -  {kernel_load_completed},
                -  {progress, loaded},
                -  {kernelProcess, Name, {Mod, Func, Args}},
                +  {kernel_load_completed},
                +  {progress, loaded},
                +  {kernelProcess, Name, {Mod, Func, Args}},
                   ...
                -  {apply, {Mod, Func, Args}},
                +  {apply, {Mod, Func, Args}},
                   ...
                -  {progress, started}]}.
                • Name = string() - Defines the system name.

                • Vsn = string() - Defines the system version.

                • {progress, Term} - Sets the "progress" of the initialization program. + {progress, started}]}.

                • Name = string() - Defines the system name.

                • Vsn = string() - Defines the system version.

                • {progress, Term} - Sets the "progress" of the initialization program. The init:get_status/0 function returns the current value of the progress, which is {InternalStatus,Term}.

                • {path, [Dir]} - Dir is a string. This argument sets the load path of the system to [Dir]. The load path used to load modules is obtained from the /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (7057)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/notes.html 2026-08-21 04:00:27.096344709 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/notes.html 2026-08-21 04:00:27.096344709 +0000 @@ -97,9 +97,9 @@ USM credentials, supporting SNMPv3 USM EngineID discovery as described in RFC 3414, Section 4. The failed_processing_message variant has been added to the - snmpm:user:handle_error/3 callback type specification.

                  Own Id: OTP-20056 Aux Id: GH-7156, ERIERL-1312, PR-10911

                SNMP 5.20.1

                Improvements and New Features

                • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

                  A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

                  make release_docs places the documentation in the released code under the doc folder.

                  make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

                  The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

                  Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

                  Improves the source Software-Bill-of-Materials

                  • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
                  • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
                  • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

                  Own Id: OTP-19886 Aux Id: PR-10434

                SNMP 5.20

                Fixed Bugs and Malfunctions

                • Fixed a bug where running snmp:config() from Elixir would crash due to io:get_line/1 returning unexpected datatype.

                  Own Id: OTP-19883 Aux Id: PR-10326

                Improvements and New Features

                • Inherit ERL_DETERMINISTIC variable for compiling snmp_pdus_basic.beam.

                  Own Id: OTP-19885 Aux Id: PR-10288

                SNMP 5.19.1

                Fixed Bugs and Malfunctions

                • Using ASN.1 generated code for decode/encode of basic types, starting with Counter64.

                  Own Id: OTP-19619 Aux Id: GH-5756, PR-9869

                Improvements and New Features

                • Reworked the timer handling of the (SNMP) manager start notification feature.

                  Own Id: OTP-19696 Aux Id: PR-10014

                • Added missing specs to already documented functions.

                  Own Id: OTP-19723 Aux Id: PR-10087

                SNMP 5.19

                Improvements and New Features

                • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

                  All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

                  -type meter() :: integer().
                  --type foot() :: integer().

                  Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

                  -nominal meter() :: integer().
                  --nominal foot() :: integer().

                  More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

                  Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

                  Own Id: OTP-19364 Aux Id: PR-9079

                • Added support for compiling Erlang/OTP for Windows on ARM64.

                  Own Id: OTP-19480 Aux Id: PR-8734

                • When compiling C/C++ code on Unix systems, the compiler hardening flags suggested by the Open Source Security Foundation are now enabled by default. To disable them, pass --disable-security-hardening-flags to configure.

                  Own Id: OTP-19519 Aux Id: PR-9441

                • Add copyright notice to files that still had none.

                  Own Id: OTP-19572

                • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

                  Own Id: OTP-19575 Aux Id: PR-9670

                SNMP 5.18.2

                Fixed Bugs and Malfunctions

                • When manager receives an v3 inform (request) it used engine-id and full address (including port number) to check if engine was known. This did not work if agent used ephemeral ports for notifications. Has now been changed to only use (context) engine-id and address (without port).

                  Own Id: OTP-19562 Aux Id: ERIERL-1207

                • Fixed snmp_generic (dialyzer) spec for function table_func.

                  Own Id: OTP-19568 Aux Id: ERIERL-1211

                SNMP 5.18.1

                Fixed Bugs and Malfunctions

                • SNMP Agent transports type (intAgentTransports) was incorrectly not documented as a list of transports. + snmpm:user:handle_error/3 callback type specification.

                  Own Id: OTP-20056 Aux Id: GH-7156, ERIERL-1312, PR-10911

                SNMP 5.20.1

                Improvements and New Features

                • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

                  A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

                  make release_docs places the documentation in the released code under the doc folder.

                  make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

                  The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

                  Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

                  Improves the source Software-Bill-of-Materials

                  • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
                  • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
                  • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

                  Own Id: OTP-19886 Aux Id: PR-10434

                SNMP 5.20

                Fixed Bugs and Malfunctions

                • Fixed a bug where running snmp:config() from Elixir would crash due to io:get_line/1 returning unexpected datatype.

                  Own Id: OTP-19883 Aux Id: PR-10326

                Improvements and New Features

                • Inherit ERL_DETERMINISTIC variable for compiling snmp_pdus_basic.beam.

                  Own Id: OTP-19885 Aux Id: PR-10288

                SNMP 5.19.1

                Fixed Bugs and Malfunctions

                • Using ASN.1 generated code for decode/encode of basic types, starting with Counter64.

                  Own Id: OTP-19619 Aux Id: GH-5756, PR-9869

                Improvements and New Features

                • Reworked the timer handling of the (SNMP) manager start notification feature.

                  Own Id: OTP-19696 Aux Id: PR-10014

                • Added missing specs to already documented functions.

                  Own Id: OTP-19723 Aux Id: PR-10087

                SNMP 5.19

                Improvements and New Features

                • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

                  All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

                  -type meter() :: integer().
                  +-type foot() :: integer().

                  Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

                  -nominal meter() :: integer().
                  +-nominal foot() :: integer().

                  More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

                  Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

                  Own Id: OTP-19364 Aux Id: PR-9079

                • Added support for compiling Erlang/OTP for Windows on ARM64.

                  Own Id: OTP-19480 Aux Id: PR-8734

                • When compiling C/C++ code on Unix systems, the compiler hardening flags suggested by the Open Source Security Foundation are now enabled by default. To disable them, pass --disable-security-hardening-flags to configure.

                  Own Id: OTP-19519 Aux Id: PR-9441

                • Add copyright notice to files that still had none.

                  Own Id: OTP-19572

                • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

                  Own Id: OTP-19575 Aux Id: PR-9670

                SNMP 5.18.2

                Fixed Bugs and Malfunctions

                • When manager receives an v3 inform (request) it used engine-id and full address (including port number) to check if engine was known. This did not work if agent used ephemeral ports for notifications. Has now been changed to only use (context) engine-id and address (without port).

                  Own Id: OTP-19562 Aux Id: ERIERL-1207

                • Fixed snmp_generic (dialyzer) spec for function table_func.

                  Own Id: OTP-19568 Aux Id: ERIERL-1211

                SNMP 5.18.1

                Fixed Bugs and Malfunctions

                • SNMP Agent transports type (intAgentTransports) was incorrectly not documented as a list of transports. Also add a couple of config file generation examples.

                  Own Id: OTP-19438 Aux Id: ERIERL-1180

                SNMP 5.18

                Improvements and New Features

                • Erlang/OTP type specifications has been updated to eliminate overlapping domains.

                  Own Id: OTP-19310 Aux Id: GH-8810, GH-8821, PR-8986

                SNMP 5.17

                Fixed Bugs and Malfunctions

                • Man pages are now available for erl, erlc, dialyzer, and all other programs that are included in Erlang/OTP.

                  Own Id: OTP-19201 Aux Id: PR-8740

                Improvements and New Features

                • Figures in the documentation have been improved.

                  Own Id: OTP-19130 Aux Id: PR-7226

                SNMP 5.16

                Improvements and New Features

                SNMP 5.15

                Improvements and New Features

                • Make snmp handle gen_udp with socket backend on Windows (completion).

                  Own Id: OTP-18598 Aux Id: OTP-18029

                SNMP 5.14

                Improvements and New Features

                • The implementation has been fixed to use proc_lib:init_fail/2,3 where appropriate, instead of proc_lib:init_ack/1,2.

                  * POTENTIAL INCOMPATIBILITY *

                  Own Id: OTP-18490 Aux Id: OTP-18471, GH-6339, PR-6843

                SNMP 5.13.5

                Improvements and New Features

                • Attempts to minimize the number of the error reports during a failed agent init.

                  Own Id: OTP-18422 Aux Id: ERIERL-873

                SNMP 5.13.4

                Improvements and New Features

                • Replace size/1 with either tuple_size/1 or byte_size/1

                  The size/1 BIF is not optimized by the JIT, and its use can /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> snmp - 5.20.2.1 - urn:uuid:069a43b3-78af-e1c0-9750-fe7b5a26db87 + urn:uuid:85f3a7eb-c409-3d6e-cede-cfa2fa8bef48 en - 2026-08-21T03:48:09Z + 2042-09-22T17:06:54Z /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/notes.xhtml differs (HTML document, ASCII text, with very long lines (5657)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -25,9 +25,9 @@ USM credentials, supporting SNMPv3 USM EngineID discovery as described in RFC 3414, Section 4. The failed_processing_message variant has been added to the - snmpm:user:handle_error/3 callback type specification.

                  Own Id: OTP-20056 Aux Id: GH-7156, ERIERL-1312, PR-10911

                SNMP 5.20.1

                Improvements and New Features

                • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

                  A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

                  make release_docs places the documentation in the released code under the doc folder.

                  make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

                  The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

                  Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

                  Improves the source Software-Bill-of-Materials

                  • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
                  • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
                  • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

                  Own Id: OTP-19886 Aux Id: PR-10434

                SNMP 5.20

                Fixed Bugs and Malfunctions

                • Fixed a bug where running snmp:config() from Elixir would crash due to io:get_line/1 returning unexpected datatype.

                  Own Id: OTP-19883 Aux Id: PR-10326

                Improvements and New Features

                • Inherit ERL_DETERMINISTIC variable for compiling snmp_pdus_basic.beam.

                  Own Id: OTP-19885 Aux Id: PR-10288

                SNMP 5.19.1

                Fixed Bugs and Malfunctions

                • Using ASN.1 generated code for decode/encode of basic types, starting with Counter64.

                  Own Id: OTP-19619 Aux Id: GH-5756, PR-9869

                Improvements and New Features

                • Reworked the timer handling of the (SNMP) manager start notification feature.

                  Own Id: OTP-19696 Aux Id: PR-10014

                • Added missing specs to already documented functions.

                  Own Id: OTP-19723 Aux Id: PR-10087

                SNMP 5.19

                Improvements and New Features

                • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

                  All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

                  -type meter() :: integer().
                  --type foot() :: integer().

                  Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

                  -nominal meter() :: integer().
                  --nominal foot() :: integer().

                  More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

                  Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

                  Own Id: OTP-19364 Aux Id: PR-9079

                • Added support for compiling Erlang/OTP for Windows on ARM64.

                  Own Id: OTP-19480 Aux Id: PR-8734

                • When compiling C/C++ code on Unix systems, the compiler hardening flags suggested by the Open Source Security Foundation are now enabled by default. To disable them, pass --disable-security-hardening-flags to configure.

                  Own Id: OTP-19519 Aux Id: PR-9441

                • Add copyright notice to files that still had none.

                  Own Id: OTP-19572

                • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

                  Own Id: OTP-19575 Aux Id: PR-9670

                SNMP 5.18.2

                Fixed Bugs and Malfunctions

                • When manager receives an v3 inform (request) it used engine-id and full address (including port number) to check if engine was known. This did not work if agent used ephemeral ports for notifications. Has now been changed to only use (context) engine-id and address (without port).

                  Own Id: OTP-19562 Aux Id: ERIERL-1207

                • Fixed snmp_generic (dialyzer) spec for function table_func.

                  Own Id: OTP-19568 Aux Id: ERIERL-1211

                SNMP 5.18.1

                Fixed Bugs and Malfunctions

                • SNMP Agent transports type (intAgentTransports) was incorrectly not documented as a list of transports. + snmpm:user:handle_error/3 callback type specification.

                  Own Id: OTP-20056 Aux Id: GH-7156, ERIERL-1312, PR-10911

                SNMP 5.20.1

                Improvements and New Features

                • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

                  A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

                  make release_docs places the documentation in the released code under the doc folder.

                  make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

                  The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

                  Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

                  Improves the source Software-Bill-of-Materials

                  • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
                  • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
                  • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

                  Own Id: OTP-19886 Aux Id: PR-10434

                SNMP 5.20

                Fixed Bugs and Malfunctions

                • Fixed a bug where running snmp:config() from Elixir would crash due to io:get_line/1 returning unexpected datatype.

                  Own Id: OTP-19883 Aux Id: PR-10326

                Improvements and New Features

                • Inherit ERL_DETERMINISTIC variable for compiling snmp_pdus_basic.beam.

                  Own Id: OTP-19885 Aux Id: PR-10288

                SNMP 5.19.1

                Fixed Bugs and Malfunctions

                • Using ASN.1 generated code for decode/encode of basic types, starting with Counter64.

                  Own Id: OTP-19619 Aux Id: GH-5756, PR-9869

                Improvements and New Features

                • Reworked the timer handling of the (SNMP) manager start notification feature.

                  Own Id: OTP-19696 Aux Id: PR-10014

                • Added missing specs to already documented functions.

                  Own Id: OTP-19723 Aux Id: PR-10087

                SNMP 5.19

                Improvements and New Features

                • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

                  All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

                  -type meter() :: integer().
                  +-type foot() :: integer().

                  Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

                  -nominal meter() :: integer().
                  +-nominal foot() :: integer().

                  More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

                  Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

                  Own Id: OTP-19364 Aux Id: PR-9079

                • Added support for compiling Erlang/OTP for Windows on ARM64.

                  Own Id: OTP-19480 Aux Id: PR-8734

                • When compiling C/C++ code on Unix systems, the compiler hardening flags suggested by the Open Source Security Foundation are now enabled by default. To disable them, pass --disable-security-hardening-flags to configure.

                  Own Id: OTP-19519 Aux Id: PR-9441

                • Add copyright notice to files that still had none.

                  Own Id: OTP-19572

                • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

                  Own Id: OTP-19575 Aux Id: PR-9670

                SNMP 5.18.2

                Fixed Bugs and Malfunctions

                • When manager receives an v3 inform (request) it used engine-id and full address (including port number) to check if engine was known. This did not work if agent used ephemeral ports for notifications. Has now been changed to only use (context) engine-id and address (without port).

                  Own Id: OTP-19562 Aux Id: ERIERL-1207

                • Fixed snmp_generic (dialyzer) spec for function table_func.

                  Own Id: OTP-19568 Aux Id: ERIERL-1211

                SNMP 5.18.1

                Fixed Bugs and Malfunctions

                • SNMP Agent transports type (intAgentTransports) was incorrectly not documented as a list of transports. Also add a couple of config file generation examples.

                  Own Id: OTP-19438 Aux Id: ERIERL-1180

                SNMP 5.18

                Improvements and New Features

                • Erlang/OTP type specifications has been updated to eliminate overlapping domains.

                  Own Id: OTP-19310 Aux Id: GH-8810, GH-8821, PR-8986

                SNMP 5.17

                Fixed Bugs and Malfunctions

                • Man pages are now available for erl, erlc, dialyzer, and all other programs that are included in Erlang/OTP.

                  Own Id: OTP-19201 Aux Id: PR-8740

                Improvements and New Features

                • Figures in the documentation have been improved.

                  Own Id: OTP-19130 Aux Id: PR-7226

                SNMP 5.16

                Improvements and New Features

                SNMP 5.15

                Improvements and New Features

                • Make snmp handle gen_udp with socket backend on Windows (completion).

                  Own Id: OTP-18598 Aux Id: OTP-18029

                SNMP 5.14

                Improvements and New Features

                • The implementation has been fixed to use proc_lib:init_fail/2,3 where appropriate, instead of proc_lib:init_ack/1,2.

                  * POTENTIAL INCOMPATIBILITY *

                  Own Id: OTP-18490 Aux Id: OTP-18471, GH-6339, PR-6843

                SNMP 5.13.5

                Improvements and New Features

                • Attempts to minimize the number of the error reports during a failed agent init.

                  Own Id: OTP-18422 Aux Id: ERIERL-873

                SNMP 5.13.4

                Improvements and New Features

                • Replace size/1 with either tuple_size/1 or byte_size/1

                  The size/1 BIF is not optimized by the JIT, and its use can /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_advanced_agent.xhtml differs (HTML document, ASCII text, with very long lines (1006)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_advanced_agent.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_advanced_agent.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -149,48 +149,48 @@ empName DisplayString, empTelNo DisplayString, empStatus RowStatus - }

    The corresponding Mnesia table is specified as follows:

    mnesia:create_table([{name, employees},
    -                     {snmp, [{key, {integer, string}}]},
    -                     {attributes, [key, telno, row_status]}]).

    Note

    In the Mnesia tables, the two key columns are stored as a tuple with two -elements. Therefore, the arity of the table is 3.

    Instrumentation Functions

    The MIB table shown in the previous section can be compiled as follows:

    1> snmpc:compile("EmpMIB", [{db, mnesia}]).

    This is all that has to be done! Now the manager can read, add, and modify + }

    The corresponding Mnesia table is specified as follows:

    mnesia:create_table([{name, employees},
    +                     {snmp, [{key, {integer, string}}]},
    +                     {attributes, [key, telno, row_status]}]).

    Note

    In the Mnesia tables, the two key columns are stored as a tuple with two +elements. Therefore, the arity of the table is 3.

    Instrumentation Functions

    The MIB table shown in the previous section can be compiled as follows:

    1> snmpc:compile("EmpMIB", [{db, mnesia}]).

    This is all that has to be done! Now the manager can read, add, and modify rows. Also, you can use the ordinary Mnesia API to access the table from your programs. The only explicit action is to create the Mnesia table, an action the user has to perform in order to create the required table schemas.

    Adding Own Actions

    It is often necessary to take some specific action when a table is modified. This is accomplished with an instrumentation function. It executes some specific code when the table is set, and passes all other requests down to the -pre-defined function.

    The following example illustrates this idea:

    emp_table(set, RowIndex, Cols) ->
    -    notify_internal_resources(RowIndex, Cols),
    -    snmp_generic:table_func(set, RowIndex, Cols, {empTable, mnesia});
    -emp_table(Op, RowIndex, Cols) ->
    -    snmp_generic:table_func(Op, RowIndex, Cols, {empTable, mnesia}).

    The default instrumentation functions are defined in the module snmp_generic. +pre-defined function.

    The following example illustrates this idea:

    emp_table(set, RowIndex, Cols) ->
    +    notify_internal_resources(RowIndex, Cols),
    +    snmp_generic:table_func(set, RowIndex, Cols, {empTable, mnesia});
    +emp_table(Op, RowIndex, Cols) ->
    +    snmp_generic:table_func(Op, RowIndex, Cols, {empTable, mnesia}).

    The default instrumentation functions are defined in the module snmp_generic. Refer to the Reference Manual, section SNMP, module snmp_generic for details.

    Extending the Mnesia Table

    A table may contain columns that are used internally, but should not be visible to a manager. These internal columns must be the last columns in the table. The set operation will not work with this arrangement, because there are columns that the agent does not know about. This situation is handled by adding values for the internal columns in the set function.

    To illustrate this, suppose we extend our Mnesia empTable with one internal column. We create it as before, but with an arity of 4, by adding another -attribute.

    mnesia:create_table([{name, employees},
    -                     {snmp, [{key, {integer, string}}]},
    -                     {attributes, {key, telno, row_status, internal_col}}]).

    The last column is the internal column. When performing a set operation, which +attribute.

    mnesia:create_table([{name, employees},
    +                     {snmp, [{key, {integer, string}}]},
    +                     {attributes, {key, telno, row_status, internal_col}}]).

    The last column is the internal column. When performing a set operation, which creates a row, we must give a value to the internal column. The instrumentation -functions will now look as follows:

    -define(createAndGo, 4).
    --define(createAndWait, 5).
    +functions will now look as follows:

    -define(createAndGo, 4).
    +-define(createAndWait, 5).
     
    -emp_table(set, RowIndex, Cols) ->
    -  notify_internal_resources(RowIndex, Cols),
    +emp_table(set, RowIndex, Cols) ->
    +  notify_internal_resources(RowIndex, Cols),
       NewCols =
    -    case is_row_created(empTable, Cols) of
    -      true -> Cols ++ [{4, "internal"}]; % add internal column
    +    case is_row_created(empTable, Cols) of
    +      true -> Cols ++ [{4, "internal"}]; % add internal column
           false -> Cols                      % keep original cols
       end,
    -  snmp_generic:table_func(set, RowIndex, NewCols, {empTable, mnesia});
    -emp_table(Op, RowIndex, Cols) ->
    -  snmp_generic:table_func(Op, RowIndex, Cols, {empTable, mnesia}).
    +  snmp_generic:table_func(set, RowIndex, NewCols, {empTable, mnesia});
    +emp_table(Op, RowIndex, Cols) ->
    +  snmp_generic:table_func(Op, RowIndex, Cols, {empTable, mnesia}).
     
    -is_row_created(Name, Cols) ->
    -  case snmp_generic:get_status_col(Name, Cols) of
    -    {ok, ?createAndGo} -> true;
    -    {ok, ?createAndWait} -> true;
    +is_row_created(Name, Cols) ->
    +  case snmp_generic:get_status_col(Name, Cols) of
    +    {ok, ?createAndGo} -> true;
    +    {ok, ?createAndWait} -> true;
         _ -> false
       end.

    If a row is created, we always set the internal column to "internal".

    Deviations from the Standard

    In some aspects the agent does not implement SNMP fully. Here are the differences:

    • The default functions and snmp_generic cannot handle an object of type /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_agent_config_files.xhtml differs (HTML document, ASCII text, with very long lines (1549)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_agent_config_files.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_agent_config_files.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -36,30 +36,30 @@ config_err/2 of the error report module at start-up.

      Agent Information

      The agent information should be stored in a file called agent.conf.

      Each entry is a tuple of size two:

      {AgentVariable, Value}.

      • AgentVariable is one of the variables in SNMP-FRAMEWORK-MIB or one of the internal variables intAgentUDPPort, which defines which UDP port the agent listens to, or intAgentTransports, which defines the transport domains and -addresses of the agent.
      • Value is the value for the variable.

      The following example shows an agent.conf file:

      {intAgentUDPPort, 4000}.
      -{intAgentTransports,
      - [{transportDomainUdpIpv4, {141,213,11,24}},
      -  {transportDomainUdpIpv6, {0,0,0,0,0,0,0,1}}]}.
      -{snmpEngineID, "mbj's engine"}.
      -{snmpEngineMaxMessageSize, 484}.

      And this is a code (snippet) example of how to generate this file in runtime:

      AgentDir    = "/tmp",
      +addresses of the agent.
    • Value is the value for the variable.

    The following example shows an agent.conf file:

    {intAgentUDPPort, 4000}.
    +{intAgentTransports,
    + [{transportDomainUdpIpv4, {141,213,11,24}},
    +  {transportDomainUdpIpv6, {0,0,0,0,0,0,0,1}}]}.
    +{snmpEngineID, "mbj's engine"}.
    +{snmpEngineMaxMessageSize, 484}.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir    = "/tmp",
     AgentPort   = 4000,
    -Transports  = [{transportDomainUdpIpv4, {141,213,11,24}},
    -               {transportDomainUdpIpv6, {0,0,0,0,0,0,0,1}}],
    +Transports  = [{transportDomainUdpIpv4, {141,213,11,24}},
    +               {transportDomainUdpIpv6, {0,0,0,0,0,0,0,1}}],
     EngineID    = "mbj's engine",
     MMS         = 484,
     AgentConfig =
    -   [snmpa_conf:agent_entry(intAgentUDPPort,          AgentPort),
    -    snmpa_conf:agent_entry(intAgentTransports,       Transports),
    -    snmpa_conf:agent_entry(snmpEngineID,             EngineID),
    -    snmpa_conf:agent_entry(snmpEngineMaxMessageSize, MMS)],
    -snmpa_conf:write_agent_config(AgentDir, AgentConfig),

    These are the supported entries and their value types:

          {snmpEngine,               string()}.                     % Mandatory
    -      {snmpEngineMaxMessageSize, snmp_framework_mib:max_message_size()}.  % Mandatory
    -      {intAgentUDPPort,          inet:port_number()}.                      % Optional
    -      {intAgentTransports,       [snmpa_conf:intAgentTransport()]}.   % Mandatory

    If a "traditional" transport is specified (without explicit Kind, handling + [snmpa_conf:agent_entry(intAgentUDPPort, AgentPort), + snmpa_conf:agent_entry(intAgentTransports, Transports), + snmpa_conf:agent_entry(snmpEngineID, EngineID), + snmpa_conf:agent_entry(snmpEngineMaxMessageSize, MMS)], +snmpa_conf:write_agent_config(AgentDir, AgentConfig),

    These are the supported entries and their value types:

          {snmpEngine,               string()}.                     % Mandatory
    +      {snmpEngineMaxMessageSize, snmp_framework_mib:max_message_size()}.  % Mandatory
    +      {intAgentUDPPort,          inet:port_number()}.                      % Optional
    +      {intAgentTransports,       [snmpa_conf:intAgentTransport()]}.   % Mandatory

    If a "traditional" transport is specified (without explicit Kind, handling both requests and traps) for a transport domain, its not possible to also specify a transport (for that domain) with a specific Kind. This is for -example, not allowed:

     [{transportDomainUdpIpv4, {{141,213,11,24}, 4000}},
    -  {transportDomainUdpIpv4, {{141,213,11,24}, 4001}, trap_sender}].

    Note that only one transport per kind for each transport domain can be +example, not allowed:

     [{transportDomainUdpIpv4, {{141,213,11,24}, 4000}},
    +  {transportDomainUdpIpv4, {{141,213,11,24}, 4001}, trap_sender}].

    Note that only one transport per kind for each transport domain can be configured.

    PortInfo system is used to indicate that the 'system' should choose (the way port number '0' (zero) is normally used). Port info '0' (zero) cannot be used for this, since it is (internally) used to represent the 'default' port number.

    In the traditional transport entries, when the Addr value does not contain a @@ -74,32 +74,32 @@ default context "" need not be present.

    Each row defines a context in the agent. This information is used in the table vacmContextTable in the SNMP-VIEW-BASED-ACM-MIB.

    Each entry is a term:

    ContextName.

    • ContextName is a string.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir      = "/tmp",
     ContextConfig =
    -   [snmpa_conf:context_entry("foo"),
    -    snmpa_conf:context_entry("bar")],
    -snmpa_conf:write_context_config(AgentDir, ContextConfig),

    System Information

    The system information should be stored in a file called standard.conf.

    Each entry is a tuple of size two:

    {SystemVariable, Value}.

    • SystemVariable is one of the variables in the system group, or -snmpEnableAuthenTraps.
    • Value is the value for the variable.

    The following example shows a valid standard.conf file:

    {sysDescr, "Erlang SNMP agent"}.
    -{sysObjectID, [1,2,3]}.
    -{sysContact, "(mbj,eklas)@erlang.ericsson.se"}.
    -{sysName, "test"}.
    -{sysServices, 72}.
    -{snmpEnableAuthenTraps, enabled}.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir  = "/tmp",
    +   [snmpa_conf:context_entry("foo"),
    +    snmpa_conf:context_entry("bar")],
    +snmpa_conf:write_context_config(AgentDir, ContextConfig),

    System Information

    The system information should be stored in a file called standard.conf.

    Each entry is a tuple of size two:

    {SystemVariable, Value}.

    • SystemVariable is one of the variables in the system group, or +snmpEnableAuthenTraps.
    • Value is the value for the variable.

    The following example shows a valid standard.conf file:

    {sysDescr, "Erlang SNMP agent"}.
    +{sysObjectID, [1,2,3]}.
    +{sysContact, "(mbj,eklas)@erlang.ericsson.se"}.
    +{sysName, "test"}.
    +{sysServices, 72}.
    +{snmpEnableAuthenTraps, enabled}.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir  = "/tmp",
     StdConfig =
    -   [snmpa_conf:standard_entry(sysDescr,    "Erlang SNMP agent"),
    -    snmpa_conf:standard_entry(sysObjectID, [1,2,3]),
    -    snmpa_conf:standard_entry(sysContact,  "(mbj,eklas)@erlang.ericsson.se"),
    -    snmpa_conf:standard_entry(sysName,     "test"),
    -    snmpa_conf:standard_entry(sysServices, 72),
    -    snmpa_conf:standard_entry(snmpEnableAuthenTraps, enabled)],
    -snmpa_conf:write_standard_config(AgentDir, StdConfig),

    A value must be provided for all variables, which lack default values in the + [snmpa_conf:standard_entry(sysDescr, "Erlang SNMP agent"), + snmpa_conf:standard_entry(sysObjectID, [1,2,3]), + snmpa_conf:standard_entry(sysContact, "(mbj,eklas)@erlang.ericsson.se"), + snmpa_conf:standard_entry(sysName, "test"), + snmpa_conf:standard_entry(sysServices, 72), + snmpa_conf:standard_entry(snmpEnableAuthenTraps, enabled)], +snmpa_conf:write_standard_config(AgentDir, StdConfig),

    A value must be provided for all variables, which lack default values in the MIB.

    Communities

    The community information should be stored in a file called community.conf. It must be present if the agent is configured for SNMPv1 or SNMPv2c.

    An SNMP community is a relationship between an SNMP agent and a set of SNMP managers that defines authentication, access control and proxy characteristics.

    The corresponding table is snmpCommunityTable in the SNMP-COMMUNITY-MIB.

    Each entry is a term:

    {CommunityIndex, CommunityName, SecurityName, ContextName, TransportTag}.

    • CommunityIndex is a non-empty string.
    • CommunityName is a string.
    • SecurityName is a string.
    • ContextName is a string.
    • TransportTag is a string.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir        = "/tmp",
     CommunityConfig =
    -   [snmpa_conf:community_entry("public"),
    -    snmpa_conf:community_entry("all-rights"),
    -    snmpa_conf:community_entry("standard trap",
    -                               "standard trap", "initial", "", "")],
    -snmpa_conf:write_community_config(AgentDir, CommunityConfig),

    MIB Views for VACM

    The information about MIB Views for VACM should be stored in a file called + [snmpa_conf:community_entry("public"), + snmpa_conf:community_entry("all-rights"), + snmpa_conf:community_entry("standard trap", + "standard trap", "initial", "", "")], +snmpa_conf:write_community_config(AgentDir, CommunityConfig),

    MIB Views for VACM

    The information about MIB Views for VACM should be stored in a file called vacm.conf.

    The corresponding tables are vacmSecurityToGroupTable, vacmAccessTable and vacmViewTreeFamilyTable in the SNMP-VIEW-BASED-ACM-MIB.

    Each entry is one of the terms, one entry corresponds to one row in one of the tables.

    {vacmSecurityToGroup, SecModel, SecName, GroupName}.

    {vacmAccess, GroupName, Prefix, SecModel, SecLevel, Match, ReadView, WriteView, NotifyView}.

    {vacmViewTreeFamily, ViewIndex, ViewSubtree, ViewStatus, ViewMask}.

    • SecModel is any, v1, v2c, or usm.
    • SecName is a string.
    • GroupName is a string.
    • Prefix is a string.
    • SecLevel is noAuthNoPriv, authNoPriv, or authPriv
    • Match is prefix or exact.
    • ReadView is a string.
    • WriteView is a string.
    • NotifyView is a string.
    • ViewIndex is an integer.
    • ViewSubtree is a list of integer.
    • ViewStatus is either included or excluded
    • ViewMask is either null or a list of ones and zeros. Ones nominate that an @@ -108,17 +108,17 @@ regarded as all ones. null is shorthand for a mask with all ones.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir   = "/tmp",
     SecName    = "plain",
     VacmConfig =
    -   [%%                        SecModel, SecName, GroupName
    -    snmpa_conf:vacm_s2g_entry(usm, SecName, SecName),
    +   [%%                        SecModel, SecName, GroupName
    +    snmpa_conf:vacm_s2g_entry(usm, SecName, SecName),
     
         %%                        GroupName, Prefix, SecModel,
    -    snmpa_conf:vacm_acc_entry(SecName, "", any,
    +    snmpa_conf:vacm_acc_entry(SecName, "", any,
         %%                        SecLevel, Match, RV, WV, NV
    -                              noAuthNoPriv, exact, "all", "all", "all"),
    +                              noAuthNoPriv, exact, "all", "all", "all"),
     
         %%                        ViewName, ViewSubtree, ViewType, ViewMask
    -    snmpa_conf:vacm_vtf_entry("restricted", [1,3,6,1], included, null)],
    -snmpa_conf:write_vacm_config(AgentDir, VacmConfig),

    Security data for USM

    The information about Security data for USM should be stored in a file called + snmpa_conf:vacm_vtf_entry("restricted", [1,3,6,1], included, null)], +snmpa_conf:write_vacm_config(AgentDir, VacmConfig),

    Security data for USM

    The information about Security data for USM should be stored in a file called usm.conf, which must be present if the agent is configured for SNMPv3.

    The corresponding table is usmUserTable in the SNMP-USER-BASED-SM-MIB (adjusted according to SNMP-USM-HMAC-SHA2-MIB).

    Each entry is a term:

    {EngineID, UserName, SecName, Clone, AuthP, AuthKeyC, OwnAuthKeyC, PrivP, PrivKeyC, OwnPrivKeyC, Public, AuthKey, PrivKey}.

    • EngineID is a string.

    • UserName is a string.

    • SecName is a string.

    • Clone is zeroDotZero or a list of integers.

    • AuthP is a usmNoAuthProtocol, usmHMACMD5AuthProtocol, usmHMACSHAAuthProtocol, usmHMAC128SHA224AuthProtocol, @@ -131,29 +131,29 @@ be 16 if usmDESPrivProtocol or usmAesCfb128Protocol is used.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir  = "/tmp",
     EngineID  = "plain engine"
     Passwd    = "FooBar Hoopla", %% This should *obviously* be choosen better
    -Secret16  = snmp:passwd2localized_key(md5, Passwd, EngineID),
    -Secret20  = snmp:passwd2localized_key(sha, Passwd, EngineID),
    +Secret16  = snmp:passwd2localized_key(md5, Passwd, EngineID),
    +Secret20  = snmp:passwd2localized_key(sha, Passwd, EngineID),
     UsmConfig =
    -   [snmpa_conf:usm_entry(EngineID, "initial", "initial", zeroDotZero,
    +   [snmpa_conf:usm_entry(EngineID, "initial", "initial", zeroDotZero,
                              usmHMACMD5AuthProtocol, "", "",
                              usmNoPrivProtocol, "", "",
    -                         "", Secret16, ""),
    +                         "", Secret16, ""),
     
    -    snmpa_conf:usm_entry(EngineID, "templateMD5", "templateMD5", zeroDotZero,
    +    snmpa_conf:usm_entry(EngineID, "templateMD5", "templateMD5", zeroDotZero,
                              usmHMACMD5AuthProtocol, "", "",
                              usmDESPrivProtocol, "", "",
    -                         "", Secret16, Secret16),
    +                         "", Secret16, Secret16),
     
    -    snmpa_conf:usm_entry(EngineID, "templateSHA", "templateSHA", zeroDotZero,
    +    snmpa_conf:usm_entry(EngineID, "templateSHA", "templateSHA", zeroDotZero,
                              usmHMACSHAAuthProtocol, "", "",
                              usmAesCfb128Protocol, "", "",
    -                         "", Secret20, Secret16)],
    -snmpa_conf:write_usm_config(AgentDir, UsmConfig),

    Notify Definitions

    The information about Notify Definitions should be stored in a file called + "", Secret20, Secret16)], +snmpa_conf:write_usm_config(AgentDir, UsmConfig),

    Notify Definitions

    The information about Notify Definitions should be stored in a file called notify.conf.

    The corresponding table is snmpNotifyTable in the SNMP-NOTIFICATION-MIB.

    Each entry is a term:

    {NotifyName, Tag, Type}.

    • NotifyName is a unique non-empty string.
    • Tag is a string.
    • Type is trap or inform.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir     = "/tmp",
     NotifyConfig =
    -   [snmpa_conf:notify_entry("standard trap",   "std_trap",   trap),
    -    snmpa_conf:notify_entry("standard inform", "std_inform", inform)],
    -snmpa_conf:write_notify_config(AgentDir, NotifyConfig),

    Target Address Definitions

    The information about Target Address Definitions should be stored in a file + [snmpa_conf:notify_entry("standard trap", "std_trap", trap), + snmpa_conf:notify_entry("standard inform", "std_inform", inform)], +snmpa_conf:write_notify_config(AgentDir, NotifyConfig),

    Target Address Definitions

    The information about Target Address Definitions should be stored in a file called target_addr.conf.

    The corresponding tables are snmpTargetAddrTable in the SNMP-TARGET-MIB and snmpTargetAddrExtTable in the SNMP-COMMUNITY-MIB.

    Each entry is a term:

    {TargetName, Domain, Addr, Timeout, RetryCount, TagList, ParamsName, EngineId}.
    or
    {TargetName, Domain, Addr, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}.

    • TargetName is a unique non-empty string.

    • Domain is one of the atoms: transportDomainUdpIpv4 | transportDomainUdpIpv6.

    • Addr is either an IpAddr or an {IpAddr, IpPort} tuple. IpAddr is @@ -164,12 +164,12 @@ configurations still work.

      Note that if EngineId has the value discovery, the agent cannot send inform messages to that manager until it has performed the discovery process with that manager.

      And this is a code (snippet) example of how to generate this file in runtime:

      AgentDir         = "/tmp",
      -Addr1            = {{1,2,3,4},     162},
      -Addr2            = {{11,21,31,41}, 162},
      +Addr1            = {{1,2,3,4},     162},
      +Addr2            = {{11,21,31,41}, 162},
       Timeout          = 1500,
       RetryCount       = 3,
       TargetAddrConfig =
      -   [snmpa_conf:target_addr_entry("Target 1",
      +   [snmpa_conf:target_addr_entry("Target 1",
                                        transportDomainUdpIpv4, Addr1,
       				 Timeout, RetryCount,
       				 "std_trap, "target_1", "",
      @@ -178,13 +178,13 @@
                                        transportDomainUdpIpv4, Addr2,
       				 Timeout, RetryCount,
       				 "std_inform, "target_2", "",
      -				 [], 2048)],
      -snmpa_conf:write_target_addr_config(AgentDir, TargetAddrConfig),

      Target Parameters Definitions

      The information about Target Parameters Definitions should be stored in a file + [], 2048)], +snmpa_conf:write_target_addr_config(AgentDir, TargetAddrConfig),

    Target Parameters Definitions

    The information about Target Parameters Definitions should be stored in a file called target_params.conf.

    The corresponding table is snmpTargetParamsTable in the SNMP-TARGET-MIB.

    Each entry is a term:

    {ParamsName, MPModel, SecurityModel, SecurityName, SecurityLevel}.

    • ParamsName is a unique non-empty string.
    • MPModel is v1, v2c or v3
    • SecurityModel is v1, v2c, or usm.
    • SecurityName is a string.
    • SecurityLevel is noAuthNoPriv, authNoPriv or authPriv.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir         = "/tmp",
     TargetAddrConfig =
    -   [snmpa_conf:target_params_entry("target_1", v1),
    -    snmpa_conf:target_params_entry("target_2", v2, "initial", noAthNoPriv],
    -snmpa_conf:write_target_params_config(AgentDir, TargetParamsConfig),
    /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_agent_funct_descr.xhtml differs (HTML document, ASCII text, with very long lines (773)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_agent_funct_descr.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_agent_funct_descr.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -164,7 +164,7 @@ MIBs are always available in all contexts.

    The ASN.1 code, the Erlang source code, and the generated .hrl files for them are provided in the distribution and are placed in the directories mibs, src, and include, respectively, in the snmp application.

    The .hrl files are generated with snmpc:mib_to_hrl/1. Include these files in -your code as in the following example:

    -include_lib("snmp/include/SNMPv2-MIB.hrl").

    The initial values for the managed objects defined in these tables, are read at +your code as in the following example:

    -include_lib("snmp/include/SNMPv2-MIB.hrl").

    The initial values for the managed objects defined in these tables, are read at start-up from a set of configuration files. These are described in Configuration Files.

    STANDARD-MIB and SNMPv2-MIB

    These MIBs contain the snmp- and system groups from MIB-II which is defined in RFC1213 (STANDARD-MIB) or RFC1907 (SNMPv2-MIB). They are implemented in the @@ -277,9 +277,9 @@ objects in this MIB are now obsolete.

    Notifications

    Notifications are defined in SMIv1 with the TRAP-TYPE macro in the definition of an MIB (see RFC1215). The corresponding macro in SMIv2 is NOTIFICATION-TYPE. When an application decides to send a notification, it calls one of the -following functions:

    snmpa:send_notification(Agent, Notification, Receiver
    -                       [, NotifyName, ContextName, Varbinds])
    -snmpa:send_trap(Agent, Notification, Community [, Receiver, Varbinds])

    providing the registered name or process identifier of the agent where the MIB, +following functions:

    snmpa:send_notification(Agent, Notification, Receiver
    +                       [, NotifyName, ContextName, Varbinds])
    +snmpa:send_trap(Agent, Notification, Community [, Receiver, Varbinds])

    providing the registered name or process identifier of the agent where the MIB, which defines the notification is loaded and the symbolic name of the notification.

    If the send_notification/3,4 function is used, all management targets are selected, as defined in RFC2273. The Receiver parameter defines where the /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_app_b.xhtml differs (HTML document, ASCII text, with very long lines (501)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_app_b.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_app_b.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -466,23 +466,23 @@ immediately removed." - SYNTAX INTEGER { + SYNTAX INTEGER { -- the following two values are states: -- these values may be read or written - active(1), - notInService(2), + active(1), + notInService(2), -- the following value is a state: -- this value may be read, but not written - notReady(3), + notReady(3), -- the following three values are -- actions: these values may be written, -- but are never read - createAndGo(4), - createAndWait(5), - destroy(6) - }

    + createAndGo(4), + createAndWait(5), + destroy(6) + }
    /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_app.xhtml differs (HTML document, ASCII text, with very long lines (984)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_app.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_app.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -20,51 +20,51 @@

    Description

    This chapter describes the snmp application in OTP. The SNMP application provides the following services:

    • a multilingual extensible SNMP agent
    • a SNMP manager
    • a MIB compiler

    Configuration

    The following configuration parameters are defined for the SNMP application. Refer to application(3) for more information about configuration parameters.

    The snmp part of the config file specifying the configuration parameters is -basically the following tuple:

          {snmp, snmp_components_config()}

    A minimal config file for starting a node with both a manager and an agent:

          [{snmp,
    -        [{agent, [{db_dir, "/tmp/snmp/agent/db"},
    -                  {config, [{dir, "/tmp/snmp/agent/conf"}]}]},
    -         {manager, [{config, [{dir, "/tmp/snmp/manager/conf"},
    -                              {db_dir, "/tmp/snmp/manager/db"}]}]}]}
    -        ]
    +basically the following tuple:

          {snmp, snmp_components_config()}

    A minimal config file for starting a node with both a manager and an agent:

          [{snmp,
    +        [{agent, [{db_dir, "/tmp/snmp/agent/db"},
    +                  {config, [{dir, "/tmp/snmp/agent/conf"}]}]},
    +         {manager, [{config, [{dir, "/tmp/snmp/manager/conf"},
    +                              {db_dir, "/tmp/snmp/manager/db"}]}]}]}
    +        ]
            }
           ].

    Each snmp component has its own set of configuration parameters, even though -some of the types are common to both components.

          snmp_components_config() -> [snmp_component_config()]
    -      snmp_component_config() -> {agent, agent_options()} | {manager, manager_options()}
    -      agent_options() = [agent_option()]
    -      agent_option() = {restart_type,     restart_type()}     |
    -                       {agent_type,       agent_type()}       |
    -                       {agent_verbosity,  verbosity()}        |
    -                       {discovery,        agent_discovery()}  |
    -                       {versions,         versions()}         |
    -                       {gb_max_vbs,       gb_max_vbs()}       |
    -                       {priority,         priority()}         |
    -                       {multi_threaded,   multi_threaded()}   |
    -                       {db_dir,           db_dir()}           |
    -                       {db_init_error,    db_init_error()}    |
    -                       {local_db,         local_db()}         |
    -                       {net_if,           agent_net_if()}     |
    -                       {mibs,             mibs()}             |
    -                       {mib_storage,      mib_storage()}      |
    -                       {mib_server,       mib_server()}       |
    -                       {audit_trail_log,  audit_trail_log()}  |
    -                       {error_report_mod, error_report_mod()} |
    -                       {note_store,       note_store()}       |
    -                       {symbolic_store,   symbolic_store()}   |
    -                       {target_cache,     target_cache()}     |
    -                       {config,           agent_config()}
    -      manager_options() = [manager_option()]
    -      manager_option() = {restart_type,             restart_type()}    |
    -                         {net_if,                   manager_net_if()}  |
    -                         {server,                   server()}          |
    -                         {note_store,               note_store()}      |
    -                         {config,                   manager_config()}  |
    -                         {inform_request_behaviour, manager_irb()}     |
    -                         {mibs,                     manager_mibs()}    |
    -                         {priority,                 priority()}        |
    -                         {audit_trail_log,          audit_trail_log()} |
    -                         {versions,                 versions()}        |
    -                         {def_user_mod,             def_user_module()  |
    -                         {def_user_data,            def_user_data()}

    Agent specific config options and types:

    • agent_type() = master | sub <optional> - If master, +some of the types are common to both components.

            snmp_components_config() -> [snmp_component_config()]
      +      snmp_component_config() -> {agent, agent_options()} | {manager, manager_options()}
      +      agent_options() = [agent_option()]
      +      agent_option() = {restart_type,     restart_type()}     |
      +                       {agent_type,       agent_type()}       |
      +                       {agent_verbosity,  verbosity()}        |
      +                       {discovery,        agent_discovery()}  |
      +                       {versions,         versions()}         |
      +                       {gb_max_vbs,       gb_max_vbs()}       |
      +                       {priority,         priority()}         |
      +                       {multi_threaded,   multi_threaded()}   |
      +                       {db_dir,           db_dir()}           |
      +                       {db_init_error,    db_init_error()}    |
      +                       {local_db,         local_db()}         |
      +                       {net_if,           agent_net_if()}     |
      +                       {mibs,             mibs()}             |
      +                       {mib_storage,      mib_storage()}      |
      +                       {mib_server,       mib_server()}       |
      +                       {audit_trail_log,  audit_trail_log()}  |
      +                       {error_report_mod, error_report_mod()} |
      +                       {note_store,       note_store()}       |
      +                       {symbolic_store,   symbolic_store()}   |
      +                       {target_cache,     target_cache()}     |
      +                       {config,           agent_config()}
      +      manager_options() = [manager_option()]
      +      manager_option() = {restart_type,             restart_type()}    |
      +                         {net_if,                   manager_net_if()}  |
      +                         {server,                   server()}          |
      +                         {note_store,               note_store()}      |
      +                         {config,                   manager_config()}  |
      +                         {inform_request_behaviour, manager_irb()}     |
      +                         {mibs,                     manager_mibs()}    |
      +                         {priority,                 priority()}        |
      +                         {audit_trail_log,          audit_trail_log()} |
      +                         {versions,                 versions()}        |
      +                         {def_user_mod,             def_user_module()  |
      +                         {def_user_data,            def_user_data()}

      Agent specific config options and types:

      • agent_type() = master | sub <optional> - If master, one master agent is started. Otherwise, no agents are started.

        Default is master.

      • agent_discovery() = [agent_discovery_opt()] <optional> - agent_discovery_opt() = {terminating, agent_terminating_discovery_opts()} | {originating, agent_originating_discovery_opts()}

        The terminating options effects discovery initiated by a manager.

        The originating options effects discovery initiated by this agent.

        For defaults see the options in agent_discovery_opt().

      • agent_terminating_discovery_opts() = [agent_terminating_discovery_opt()] <optional> - agent_terminating_discovery_opt() = {enable, boolean()} | {stage2, discovery | plain} | {trigger_username, string()}

        These are options effecting discovery terminating in this agent (i.e. /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmpa.xhtml differs (HTML document, ASCII text, with very long lines (345)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmpa.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmpa.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -3213,8 +3213,8 @@

        Load a single Mib into an agent. The MibName is the name of the Mib, -including the path to where the compiled mib is found. For example:

                  Dir = code:priv_dir(my_app) ++ "/mibs/",
        -          snmpa:load_mib(snmp_master_agent, Dir ++ "MY-MIB").
        +including the path to where the compiled mib is found. For example:

                  Dir = code:priv_dir(my_app) ++ "/mibs/",
        +          snmpa:load_mib(snmp_master_agent, Dir ++ "MY-MIB").
        @@ -3330,8 +3330,8 @@

        Load Mibs into an agent. If the agent cannot load all MIBs (the default value of the Force argument is false), it will indicate where loading was aborted. The MibName is the name of the Mib, including the path to where the compiled -mib is found. For example,

                  Dir = code:priv_dir(my_app) ++ "/mibs/",
        -          snmpa:load_mibs(snmp_master_agent, [Dir ++ "MY-MIB"]).

        If Force = true then the agent will continue attempting to load each mib even +mib is found. For example,

                  Dir = code:priv_dir(my_app) ++ "/mibs/",
        +          snmpa:load_mibs(snmp_master_agent, [Dir ++ "MY-MIB"]).

        If Force = true then the agent will continue attempting to load each mib even after failing to load a previous mib. Use with care.

        @@ -4357,8 +4357,8 @@ -

        Accepted type specifications are:

        -spec register_notification_filter(Agent, Id, Mod, Data) -> ok | {error, Reason}.
        --spec register_notification_filter(Id, Mod, Data, Where) -> ok | {error, Reason}.
        +

        Accepted type specifications are:

        -spec register_notification_filter(Agent, Id, Mod, Data) -> ok | {error, Reason}.
        +-spec register_notification_filter(Id, Mod, Data, Where) -> ok | {error, Reason}.
        @@ -4431,8 +4431,8 @@

        Registers a sub-agent under a sub-tree of another agent.

        It is easy to make mistakes when registering sub-agents and this activity should be done carefully. For example, a strange behaviour would result from the -following configuration:

        snmp_agent:register_subagent(MAPid,[1,2,3,4],SA1),
        -snmp_agent:register_subagent(SA1,[1,2,3], SA2).

        SA2 will not get requests starting with object identifier [1,2,3] since +following configuration:

        snmp_agent:register_subagent(MAPid,[1,2,3,4],SA1),
        +snmp_agent:register_subagent(SA1,[1,2,3], SA2).

        SA2 will not get requests starting with object identifier [1,2,3] since SA1 does not.

        @@ -4877,20 +4877,20 @@ Addresses and if there are no targets for which an Inform-Request is sent, Addresses is the empty list [].

        The receiver will first be sent the snmp_targets message, and then for each address in Addresses list, one of the two snmp_notification messages.

      • {Mod, Func, Args} - The info will be delivered via the function call:

        Mod:Func([Msg | Args])

        where Msg has the same content and purpose as the messages descrived above.

      Address is a management target address and Addresses is a list of management -target addresses. They are defined as followes:

              Addresses  = [address()]
      -        Address    = address()
      -        address()  = v1_address() | v3_address()
      -        v1_address() = {TDomain, TAddress}
      -        v3_address() = {{TDomain, TAddress}, V3MsgData}
      -        TDomain    = tdoamin()
      -        TAddress   = taddress()
      -        tdomain()  = The oid of snmpUDPDomain
      +target addresses. They are defined as followes:

              Addresses  = [address()]
      +        Address    = address()
      +        address()  = v1_address() | v3_address()
      +        v1_address() = {TDomain, TAddress}
      +        v3_address() = {{TDomain, TAddress}, V3MsgData}
      +        TDomain    = tdoamin()
      +        TAddress   = taddress()
      +        tdomain()  = The oid of snmpUDPDomain
                            This is the only supported transport domain.
      -        taddress() = [A1, A2, A3, A4, P1, P3]
      +        taddress() = [A1, A2, A3, A4, P1, P3]
                            The 4 first bytes makes up the IP-address and the last 2,
                            the UDP-port number.
      -        V3MsgData  = v3_msg_data()
      -        v3_msg_data() = term()

      If Receiver is a notification_delivery_info/0 record, then the information + V3MsgData = v3_msg_data() + v3_msg_data() = term()

      If Receiver is a notification_delivery_info/0 record, then the information about the notification delivery will be delivered to the receiver via the callback functions defined by the snmpa_notification_delivery_info_receiver behaviour according to the content of the notification_delivery_info/0 /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmpc_cmd.xhtml differs (HTML document, ASCII text, with very long lines (985)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmpc_cmd.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmpc_cmd.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -17,7 +17,7 @@

      snmpc

      -

      SNMP MIB compiler frontend

      Synopsis

      snmpc [options] file.mib | file.bin

      Description

      The snmpc program provides a way to run the SNMP MIB compiler of the Erlang +

      SNMP MIB compiler frontend

      Synopsis

      snmpc [options] file.mib | file.bin

      Description

      The snmpc program provides a way to run the SNMP MIB compiler of the Erlang system.

      snmpc compiles an SNMP MIB file. See compile/1,2 for more information.

      It can also be used to generate a header file (.hrl) with definitions of Erlang constants for the objects in the MIB. See mib_to_hrl/1.

      Compiler options

      The following options are supported (note that most of these relate to the /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_config.xhtml differs (HTML document, ASCII text, with very long lines (850)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_config.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_config.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -31,41 +31,41 @@ more information).

    • the database directory stores the internal database files.

    The agent and manager uses (application) configuration parameters to find out where these directories are located. The parameters should be defined in an Erlang system configuration file. The following configuration parameters are -defined for the SNMP application:

          agent_options() = [agent_option()]
    -      agent_option() = {restart_type,     restart_type()}     |
    -                       {agent_type,       agent_type()}       |
    -                       {agent_verbosity,  verbosity()}        |
    -                       {versions,         versions()}         |
    -                       {discovery,        agent_discovery()}  |
    -                       {gb_max_vbs,       gb_max_vbs()}       |
    -                       {priority,         priority()}         |
    -                       {multi_threaded,   multi_threaded()}   |
    -                       {db_dir,           db_dir()}           |
    -                       {db_init_error,    db_init_error()}    |
    -                       {local_db,         local_db()}         |
    -                       {net_if,           agent_net_if()}     |
    -                       {mibs,             mibs()}             |
    -                       {mib_storage,      mib_storage()}      |
    -                       {mib_server,       mib_server()}       |
    -                       {audit_trail_log,  audit_trail_log()}  |
    -                       {error_report_mod, error_report_mod()} |
    -                       {note_store,       note_store()}       |
    -                       {symbolic_store,   symbolic_store()}   |
    -                       {target_cache,     target_cache()}     |
    -                       {config,           agent_config()}
    -      manager_options() = [manager_option()]
    -      manager_option() = {restart_type,             restart_type()}    |
    -                         {net_if,                   manager_net_if()}  |
    -                         {server,                   server()}          |
    -                         {note_store,               note_store()}      |
    -                         {config,                   manager_config()}  |
    -                         {inform_request_behaviour, manager_irb()}     |
    -                         {mibs,                     manager_mibs()}    |
    -                         {priority,                 priority()}        |
    -                         {audit_trail_log,          audit_trail_log()} |
    -                         {versions,                 versions()}        |
    -                         {def_user_mod,             def_user_module()  |
    -                         {def_user_data,            def_user_data()}

    Agent specific config options and types:

    • agent_type() = master | sub <optional> - If master, +defined for the SNMP application:

            agent_options() = [agent_option()]
      +      agent_option() = {restart_type,     restart_type()}     |
      +                       {agent_type,       agent_type()}       |
      +                       {agent_verbosity,  verbosity()}        |
      +                       {versions,         versions()}         |
      +                       {discovery,        agent_discovery()}  |
      +                       {gb_max_vbs,       gb_max_vbs()}       |
      +                       {priority,         priority()}         |
      +                       {multi_threaded,   multi_threaded()}   |
      +                       {db_dir,           db_dir()}           |
      +                       {db_init_error,    db_init_error()}    |
      +                       {local_db,         local_db()}         |
      +                       {net_if,           agent_net_if()}     |
      +                       {mibs,             mibs()}             |
      +                       {mib_storage,      mib_storage()}      |
      +                       {mib_server,       mib_server()}       |
      +                       {audit_trail_log,  audit_trail_log()}  |
      +                       {error_report_mod, error_report_mod()} |
      +                       {note_store,       note_store()}       |
      +                       {symbolic_store,   symbolic_store()}   |
      +                       {target_cache,     target_cache()}     |
      +                       {config,           agent_config()}
      +      manager_options() = [manager_option()]
      +      manager_option() = {restart_type,             restart_type()}    |
      +                         {net_if,                   manager_net_if()}  |
      +                         {server,                   server()}          |
      +                         {note_store,               note_store()}      |
      +                         {config,                   manager_config()}  |
      +                         {inform_request_behaviour, manager_irb()}     |
      +                         {mibs,                     manager_mibs()}    |
      +                         {priority,                 priority()}        |
      +                         {audit_trail_log,          audit_trail_log()} |
      +                         {versions,                 versions()}        |
      +                         {def_user_mod,             def_user_module()  |
      +                         {def_user_data,            def_user_data()}

      Agent specific config options and types:

      • agent_type() = master | sub <optional> - If master, one master agent is started. Otherwise, no agents are started.

        Default is master.

      • agent_discovery() = [agent_discovery_opt()] <optional> - agent_discovery_opt() = {terminating, agent_terminating_discovery_opts()} | {originating, agent_originating_discovery_opts()}

        The terminating options effects discovery initiated by a manager.

        The originating options effects discovery initiated by this agent.

        For defaults see the options in agent_discovery_opt().

      • agent_terminating_discovery_opts() = [agent_terminating_discovery_opt()] <optional> - agent_terminating_discovery_opt() = {enable, boolean()} | {stage2, discovery | plain} | {trigger_username, string()}

        These are options effecting discovery terminating in this agent (i.e. @@ -424,34 +424,34 @@ configuration parameters. The verbosity itself has several _levels: silence | info | log | debug | trace. For the lowest verbosity silence, nothing is printed. The higher the verbosity, the -more is printed. Default value is always silence.

        3> snmpa:verbosity(master_agent, log).
        +more is printed. Default value is always silence.

        3> snmpa:verbosity(master_agent, log).
         ok
        -5> snmpa:verbosity(net_if, log).
        +5> snmpa:verbosity(net_if, log).
         ok
         6>
         %% Example of output from the agent when a get-next-request arrives:
         ** SNMP NET-IF LOG:
        -   got packet from {147,12,12,12}:5000
        +   got packet from {147,12,12,12}:5000
         
         ** SNMP NET-IF MPD LOG:
            v1, community: all-rights
         
         ** SNMP NET-IF LOG:
        -   got pdu from {147,12,12,12}:5000 {pdu, 'get-next-request',
        +   got pdu from {147,12,12,12}:5000 {pdu, 'get-next-request',
                                                   62612569,noError,0,
        -                                          [{varbind,[1,1],'NULL','NULL',1}]}
        +                                          [{varbind,[1,1],'NULL','NULL',1}]}
         
         ** SNMP MASTER-AGENT LOG:
        -   apply: snmp_generic,variable_func,[get,{sysDescr,persistent}]
        +   apply: snmp_generic,variable_func,[get,{sysDescr,persistent}]
         
         ** SNMP MASTER-AGENT LOG:
        -   returned: {value,"Erlang SNMP agent"}
        +   returned: {value,"Erlang SNMP agent"}
         
         ** SNMP NET-IF LOG:
        -   reply pdu: {pdu,'get-response',62612569,noError,0,
        -                   [{varbind,[1,3,6,1,2,1,1,1,0],
        +   reply pdu: {pdu,'get-response',62612569,noError,0,
        +                   [{varbind,[1,3,6,1,2,1,1,1,0],
                                      'OCTET STRING',
        -                             "Erlang SNMP agent",1}]}
        +                             "Erlang SNMP agent",1}]}
         
         ** SNMP NET-IF INFO: time in agent: 19711 mysec

        Other useful function(s) for debugging the agent are:

        • snmpa:info/0,1 - info is used to retrieve a list of miscellaneous agent information.

        • snmpa:which_aliasnames/0 - /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_generic.xhtml differs (HTML document, ASCII text, with very long lines (1710)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_generic.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_generic.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -34,9 +34,9 @@ | MIB | +---------------+ | - Association file (associates a MIB object with + Association file (associates a MIB object with | snmp_generic:table_funct - | snmp_generic:variable_func) + | snmp_generic:variable_func) +--------------------------------------+ | snmp_generic | Support for get-next, | | RowStatus operations @@ -44,7 +44,7 @@ | snmpa_local_db | Mnesia | Database +--------------+-------+---------------+ | dets | ets | -| (persistent) | | +| (persistent) | | +--------------+-------+

        Each function takes the argument NameDb, which is a tuple {Name, Db}, to identify which database the functions should use. Name is the symbolic name of the managed object as defined in the MIB, and Db is either volatile, @@ -56,35 +56,35 @@ this. Specifically, if variables are stored in Mnesia, the table snmp_variables must be created by the programmer. The record definition for this table is defined in the file snmp/include/snmp_types.hrl.

        If an instrumentation function in the association file for a variable myVar -does not have a name when compiling an MIB, the compiler generates an entry.

        {myVar, {snmp_generic, variable_func, [{myVar, Db]}}.

        And for a table:

        {myTable, {snmp_generic, table_func, [{myTable, Db]}}.

        Example

        The following example shows an implementation of a table which is stored in -Mnesia, but with some checks performed at set-request operations.

        myTable_func(new, NameDb) ->   % pass unchanged
        -  snmp_generic:table_func(new, NameDb).
        +does not have a name when compiling an MIB, the compiler generates an entry.

        {myVar, {snmp_generic, variable_func, [{myVar, Db]}}.

        And for a table:

        {myTable, {snmp_generic, table_func, [{myTable, Db]}}.

        Example

        The following example shows an implementation of a table which is stored in +Mnesia, but with some checks performed at set-request operations.

        myTable_func(new, NameDb) ->   % pass unchanged
        +  snmp_generic:table_func(new, NameDb).
         
        -myTable_func(delete, NameDb) ->   % pass unchanged
        -  snmp_generic:table_func(delete, NameDb).
        +myTable_func(delete, NameDb) ->   % pass unchanged
        +  snmp_generic:table_func(delete, NameDb).
         
         %% change row
        -myTable_func(is_set_ok, RowIndex, Cols, NameDb) ->
        -  case snmp_generic:table_func(is_set_ok, RowIndex,
        -                               Cols, NameDb) of
        -    {noError, 0} ->
        -      myApplication:is_set_ok(RowIndex, Cols);
        +myTable_func(is_set_ok, RowIndex, Cols, NameDb) ->
        +  case snmp_generic:table_func(is_set_ok, RowIndex,
        +                               Cols, NameDb) of
        +    {noError, 0} ->
        +      myApplication:is_set_ok(RowIndex, Cols);
             Err ->
               Err
           end;
         
        -myTable_func(set, RowIndex, Cols, NameDb) ->
        -  case snmp_generic:table_func(set, RowIndex, Cols,
        -                               NameDb),
        -    {noError, 0} ->
        +myTable_func(set, RowIndex, Cols, NameDb) ->
        +  case snmp_generic:table_func(set, RowIndex, Cols,
        +                               NameDb),
        +    {noError, 0} ->
               % Now the row is updated, tell the application
        -      myApplication:update(RowIndex, Cols);
        +      myApplication:update(RowIndex, Cols);
             Err ->
               Err
           end;
         
        -myTable_func(Op, RowIndex, Cols, NameDb) ->   % pass unchanged
        -  snmp_generic:table_func(Op, RowIndex, Cols, NameDb).

        The .funcs file would look like:

        {myTable, {myModule, myTable_func, [{myTable, mnesia}]}}.
        +
        myTable_func(Op, RowIndex, Cols, NameDb) -> % pass unchanged + snmp_generic:table_func(Op, RowIndex, Cols, NameDb).

        The .funcs file would look like:

        {myTable, {myModule, myTable_func, [{myTable, mnesia}]}}.
        /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_impl_example_agent.xhtml differs (HTML document, ASCII text, with very long lines (1539)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_impl_example_agent.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_impl_example_agent.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -110,108 +110,108 @@ the default implementation of it. Recall that MIBs imported by "EX1-MIB.mib" must be present and compiled in the current directory ("./STANDARD-MIB.bin","./RFC1213-MIB.bin") when compiling.

        unix> erl -config ./sys
        -1> application:start(snmp).
        +1> application:start(snmp).
         ok
        -2> snmpc:compile("EX1-MIB").
        +2> snmpc:compile("EX1-MIB").
         No accessfunction for 'friendsTable', using default.
         No accessfunction for 'myName', using default.
        -{ok, "EX1-MIB.bin"}
        -3> snmpa:load_mibs(snmp_master_agent, ["EX1-MIB"]).
        +{ok, "EX1-MIB.bin"}
        +3> snmpa:load_mibs(snmp_master_agent, ["EX1-MIB"]).
         ok

        This MIB is now loaded into the agent, and a manager can ask questions. As an example of this, we start another Erlang system and the simple Erlang manager in -the toolkit:

        1> snmp_test_mgr:start_link([{agent,"dront.ericsson.se"},{community,"all-rights"},
        +the toolkit:

        1> snmp_test_mgr:start_link([{agent,"dront.ericsson.se"},{community,"all-rights"},
          %% making it understand symbolic names: {mibs,["EX1-MIB","STANDARD-MIB"]}]).
        -{ok, <0.89.0>}
        +{ok, <0.89.0>}
         %% a get-next request with one OID.
        -2> snmp_test_mgr:gn([[1,3,6,1,3,7]]).
        +2> snmp_test_mgr:gn([[1,3,6,1,3,7]]).
         ok
         * Got PDU:
        -[myName,0] = []
        +[myName,0] = []
         %% A set-request (now using symbolic names for convenience)
        -3> snmp_test_mgr:s([{[myName,0], "Martin"}]).
        +3> snmp_test_mgr:s([{[myName,0], "Martin"}]).
         ok
         * Got PDU:
        -[myName,0] = "Martin"
        +[myName,0] = "Martin"
         %% Try the same get-next request again
        -4> snmp_test_mgr:gn([[1,3,6,1,3,7]]).
        +4> snmp_test_mgr:gn([[1,3,6,1,3,7]]).
         ok
         * Got PDU:
        -[myName,0] = "Martin"
        +[myName,0] = "Martin"
         %% ... and we got the new value.
         %% you can event do row operations. How to add a row:
        -5> snmp_test_mgr:s([{[fName,0], "Martin"}, {[fAddress,0],"home"}, {[fStatus,0],4}]).
        +5> snmp_test_mgr:s([{[fName,0], "Martin"}, {[fAddress,0],"home"}, {[fStatus,0],4}]).
          %% createAndGo
         ok
         * Got PDU:
        -[fName,0] = "Martin"
        -[fAddress,0] = "home"
        -[fStatus,0] = 4
        -6> snmp_test_mgr:gn([[myName,0]]).
        +[fName,0] = "Martin"
        +[fAddress,0] = "home"
        +[fStatus,0] = 4
        +6> snmp_test_mgr:gn([[myName,0]]).
         ok
         * Got PDU:
        -[fName,0] = "Martin"
        -7> snmp_test_mgr:gn().
        +[fName,0] = "Martin"
        +7> snmp_test_mgr:gn().
         ok
         * Got PDU:
        -[fAddress,0] = "home"
        -8> snmp_test_mgr:gn().
        +[fAddress,0] = "home"
        +8> snmp_test_mgr:gn().
         ok
         * Got PDU:
        -[fStatus,0] = 1
        +[fStatus,0] = 1
         9>

        Manual Implementation

        The following example shows a "manual" implementation of the EX1-MIB in Erlang. In this example, the values of the objects are stored in an Erlang server. The server has a 2-tuple as loop data, where the first element is the value of variable myName, and the second is a sorted list of rows in the table friendsTable. Each row is a 4-tuple.

        Note

        There are more efficient ways to create tables manually, i.e. to use the -module snmp_index.

        Code

        -module(ex1).
        --author('dummy@flop.org').
        +module snmp_index.

        Code

        -module(ex1).
        +-author('dummy@flop.org').
         %% External exports
        --export([start/0, my_name/1, my_name/2, friends_table/3]).
        +-export([start/0, my_name/1, my_name/2, friends_table/3]).
         %% Internal exports
        --export([init/0]).
        --define(status_col, 4).
        --define(active, 1).
        --define(notInService, 2).
        --define(notReady, 3).
        --define(createAndGo, 4).   % Action; written, not read
        --define(createAndWait, 5). % Action; written, not read
        --define(destroy, 6).       % Action; written, not read
        -start() ->
        -    spawn(ex1, init, []).
        +-export([init/0]).
        +-define(status_col, 4).
        +-define(active, 1).
        +-define(notInService, 2).
        +-define(notReady, 3).
        +-define(createAndGo, 4).   % Action; written, not read
        +-define(createAndWait, 5). % Action; written, not read
        +-define(destroy, 6).       % Action; written, not read
        +start() ->
        +    spawn(ex1, init, []).
         %%----------------------------------------------------------------
         %% Instrumentation function for variable myName.
         %% Returns: (get) {value, Name}
         %%          (set) noError
         %%----------------------------------------------------------------
        -my_name(get) ->
        -    ex1_server ! {self(), get_my_name},
        -    Name = wait_answer(),
        -    {value, Name}.
        -my_name(set, NewName) ->
        -    ex1_server ! {self(), {set_my_name, NewName}},
        +my_name(get) ->
        +    ex1_server ! {self(), get_my_name},
        +    Name = wait_answer(),
        +    {value, Name}.
        +my_name(set, NewName) ->
        +    ex1_server ! {self(), {set_my_name, NewName}},
             noError.
         %%----------------------------------------------------------------
         %% Instrumentation function for table friendsTable.
         %%----------------------------------------------------------------
        -friends_table(get, RowIndex, Cols) ->
        -    case get_row(RowIndex) of
        -   {ok, Row} ->
        -        get_cols(Cols, Row);
        +friends_table(get, RowIndex, Cols) ->
        +    case get_row(RowIndex) of
        +   {ok, Row} ->
        +        get_cols(Cols, Row);
            _  ->
        -        {noValue, noSuchInstance}
        +        {noValue, noSuchInstance}
             end;
        -friends_table(get_next, RowIndex, Cols) ->
        -    case get_next_row(RowIndex) of
        -   {ok, Row} ->
        -        get_next_cols(Cols, Row);
        +friends_table(get_next, RowIndex, Cols) ->
        +    case get_next_row(RowIndex) of
        +   {ok, Row} ->
        +        get_next_cols(Cols, Row);
            _  ->
        -       case get_next_row([]) of
        -     {ok, Row} ->
        +       case get_next_row([]) of
        +     {ok, Row} ->
                  % Get next cols from first row.
        -         NewCols = add_one_to_cols(Cols),
        -         get_next_cols(NewCols, Row);
        +         NewCols = add_one_to_cols(Cols),
        +         get_next_cols(NewCols, Row);
              _  ->
        -        end_of_table(Cols)
        +        end_of_table(Cols)
                 end
             end;
         %%----------------------------------------------------------------
        @@ -222,168 +222,168 @@
         %%    *) Otherwise, error (for simplicity).
         %% Otherwise, row is modified; check that row exists.
         %%----------------------------------------------------------------
        -friends_table(is_set_ok, RowIndex, Cols) ->
        +friends_table(is_set_ok, RowIndex, Cols) ->
             RowExists =
        -   case get_row(RowIndex) of
        -        {ok, _Row} -> true;
        +   case get_row(RowIndex) of
        +        {ok, _Row} -> true;
                _ -> false
            end,
        -    case is_row_status_col_changed(Cols) of
        -   {true, ?destroy} when RowExists == true ->
        -        {noError, 0};
        -   {true, ?createAndGo} when RowExists == false,
        -                                 length(Cols) == 3 ->
        -        {noError, 0};
        -   {true, _} ->
        -       {inconsistentValue, ?status_col};
        +    case is_row_status_col_changed(Cols) of
        +   {true, ?destroy} when RowExists == true ->
        +        {noError, 0};
        +   {true, ?createAndGo} when RowExists == false,
        +                                 length(Cols) == 3 ->
        +        {noError, 0};
        +   {true, _} ->
        +       {inconsistentValue, ?status_col};
            false when RowExists == true ->
        -        {noError, 0};
        +        {noError, 0};
            _ ->
        -        [{Col, _NewVal} | _Cols] = Cols,
        /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_index.xhtml differs (HTML document, ASCII text, with very long lines (807))
        --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_index.xhtml	2026-08-05 05:56:49.000000000 +0000
        +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_index.xhtml	2026-08-05 05:56:49.000000000 +0000
        @@ -29,13 +29,13 @@
         actual implementation of the table. The SNMP ordering, that is implementation of
         GET NEXT, is implemented in this module.

        For example, suppose there is an SNMP table, which is best implemented in Erlang as one process per SNMP table row. Suppose further that the INDEX in the SNMP -table is an OCTET STRING. The index structure would be created as follows:

        snmp_index:new(string)

        For each new process we create, we insert an item in an snmp_index structure:

        new_process(Name, SnmpIndex) ->
        -  Pid = start_process(),
        +table is an OCTET STRING. The index structure would be created as follows:

        snmp_index:new(string)

        For each new process we create, we insert an item in an snmp_index structure:

        new_process(Name, SnmpIndex) ->
        +  Pid = start_process(),
           NewSnmpIndex =
        -    snmp_index:insert(SnmpIndex, Name, Pid),
        +    snmp_index:insert(SnmpIndex, Name, Pid),
           <...>

        With this structure, we can now map an OBJECT IDENTIFIER in e.g. a GET NEXT -request, to the correct process:

        get_next_pid(Oid, SnmpIndex) ->
        -  {ok, {_, Pid}} = snmp_index:get_next(SnmpIndex, Oid),
        +request, to the correct process:

        get_next_pid(Oid, SnmpIndex) ->
        +  {ok, {_, Pid}} = snmp_index:get_next(SnmpIndex, Oid),
           Pid.

        Warnings

        Warning

        All API functions that update the index return a NewIndex term. This is for backward compatibility with a previous implementation that used a B+ tree written purely in Erlang for the index. The NewIndex return value /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_instr_functions.xhtml differs (HTML document, ASCII text, with very long lines (1719)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_instr_functions.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_instr_functions.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -33,8 +33,8 @@ operation is translated into a series of calls to get-next.

        Instrumentation Functions

        The following sections describe how the instrumentation functions should be defined in Erlang for the different operations. In the following, RowIndex is a list of key values for the table, and Column is a column number.

        These functions are described in detail in -Definition of Instrumentation Functions.

        New / Delete Operations

        For scalar variables:

        variable_access(new [, ExtraArg1, ...])
        -variable_access(delete [, ExtraArg1, ...])

        For tables:

        table_access(new [, ExtraArg1, ...])
        +Definition of Instrumentation Functions.

        New / Delete Operations

        For scalar variables:

        variable_access(new [, ExtraArg1, ...])
        +variable_access(delete [, ExtraArg1, ...])

        For tables:

        table_access(new [, ExtraArg1, ...])
         table_access(delete [, ExtraArg1, ...])

        These functions are called for each object in an MIB when the MIB is unloaded or loaded, respectively.

        Get Operation

        For scalar variables:

        variable_access(get [, ExtraArg1, ...])

        For tables:

        table_access(get,RowIndex,Cols [,ExtraArg1, ...])

        Cols is a list of Column. The agent will sort incoming variables so that all operations on one row (same index) will be supplied at the same time. The reason @@ -64,9 +64,9 @@ value 1, and [3, 5] is the list of requested columns. The function should now return the lexicographically next elements:

        [{[3, 1, 2], d}, {[5, 1, 2], f}]

        This is illustrated in the following table:

        GetNext from [3,1,1] and [5,1,1].

        The manager now issues the following getNext request:

        getNext{ myTable.myTableEntry.3.2.1,
                  myTable.myTableEntry.5.2.1 }

        This is transformed into one call to my_table:

        my_table(get_next, [2, 1], [3, 5])

        The function should now return:

        [{[4, 1, 1], b}, endOfTable]

        This is illustrated in the following table:

        GetNext from [3,2,1] and [5,2,1].

        The manager now issues the following getNext request:

        getNext{ myTable.myTableEntry.3.1.2,
        -         myTable.myTableEntry.4.1.2 }

        This will be transform into one call to my_table:

        my_table(get_next, [1, 2], [3, 4])

        The function should now return:

        [{[3, 2, 1], g}, {[5, 1, 1], c}]

        This is illustrated in the following table:

        GetNext from [3,1,2] and [4,1,2].

        The manager now issues the following getNext request:

        getNext{ myTable.myTableEntry,
        -         myTable.myTableEntry.1.3.2 }

        This will be transform into two calls to my_table:

        my_table(get_next, [], [0]) and
        -my_table(get_next, [3, 2], [1])

        The function should now return:

        [{[3, 1, 1], a}] and
        +         myTable.myTableEntry.4.1.2 }

        This will be transform into one call to my_table:

        my_table(get_next, [1, 2], [3, 4])

        The function should now return:

        [{[3, 2, 1], g}, {[5, 1, 1], c}]

        This is illustrated in the following table:

        GetNext from [3,1,2] and [4,1,2].

        The manager now issues the following getNext request:

        getNext{ myTable.myTableEntry,
        +         myTable.myTableEntry.1.3.2 }

        This will be transform into two calls to my_table:

        my_table(get_next, [], [0]) and
        +my_table(get_next, [3, 2], [1])

        The function should now return:

        [{[3, 1, 1], a}] and
         [{[3, 1, 1], a}]

        In both cases, the first accessible element in the table should be returned. As the key columns are not accessible, this means that the third column is the first row.

        Note

        Normally, the functions described above behave exactly as shown, but they are @@ -77,17 +77,17 @@ variables for a device, ipAdr and name with object identifiers 1.1.23.4 and 1.1.7 respectively. To access these variables, one could implement the two Erlang functions ip_access and name_access, which will be in the MIB. The -functions could be specified in a text file as follows:

        {ipAdr, {my_module, ip_access, []}}.
        +functions could be specified in a text file as follows:

        {ipAdr, {my_module, ip_access, []}}.
         % Or using the oid syntax for 'name'
        -{[1,1,7], {my_module, name_access, []}}.

        The ExtraArgument parameter is the empty list. For example, when the agent +{[1,1,7], {my_module, name_access, []}}.

        The ExtraArgument parameter is the empty list. For example, when the agent receives a get-request for the ipAdr variable, a call will be made to ip_access(get). The value returned by this function is the answer to the get-request.

        If ip_access and name_access are implemented similarly, we could write a -generic_access function using the ListOfExtraArguments:

        {ipAdr, {my_module, generic_access, ['IPADR']}}.
        +generic_access function using the ListOfExtraArguments:

        {ipAdr, {my_module, generic_access, ['IPADR']}}.
         % The mnemonic 'name' is more convenient than 1.1.7
        -{name, {my_module, generic_access, ['NAME']}}.

        When the agent receives the same get-request as above, a call will be made to -generic_access(get,'IPADR').

        Yet another possibility, closer to the hardware, could be:

        {ipAdr, {my_module, generic_access, [16#2543]}}.
        -{name, {my_module, generic_access, [16#A2B3]}}.

        Default Instrumentation

        When the MIB definition work is finished, there are two major issues left.

        • Implementing the MIB
        • Implementing a Manager Application.

        Implementing an MIB can be a tedious task. Most probably, there is a need to +{name, {my_module, generic_access, ['NAME']}}.

        When the agent receives the same get-request as above, a call will be made to +generic_access(get,'IPADR').

        Yet another possibility, closer to the hardware, could be:

        {ipAdr, {my_module, generic_access, [16#2543]}}.
        +{name, {my_module, generic_access, [16#A2B3]}}.

        Default Instrumentation

        When the MIB definition work is finished, there are two major issues left.

        • Implementing the MIB
        • Implementing a Manager Application.

        Implementing an MIB can be a tedious task. Most probably, there is a need to test the agent before all tables and variables are implemented. In this case, the default instrumentation functions are useful. The toolkit can generate default instrumentation functions for variables as well as for tables. /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_manager_config_files.xhtml differs (HTML document, ASCII text, with very long lines (1067)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_manager_config_files.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_manager_config_files.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -35,32 +35,32 @@ every transport.

      • engine_id - The SnmpEngineID as defined in SNMP-FRAMEWORK-MIB. Mandatory.

      • max_message_size - The snmpEngineMaxMessageSize as defined in SNMP-FRAMEWORK-MIB. Mandatory.

    • Value is the value for the variable.

    The legacy and intermediate variables address and domain are still supported -so old configurations will work.

    The following example shows a manager.conf file:

    {transports,       [{transportDomainUdpIpv4, {{141,213,11,24}, 5000}},
    -                    {transportDomainUdpIpv6, {{0,0,0,0,0,0,0,1}, 5000}}]}.
    -{engine_id,        "mgrEngine"}.
    -{max_message_size, 484}.

    The value of engine_id is a string, which should have a very specific +so old configurations will work.

    The following example shows a manager.conf file:

    {transports,       [{transportDomainUdpIpv4, {{141,213,11,24}, 5000}},
    +                    {transportDomainUdpIpv6, {{0,0,0,0,0,0,0,1}, 5000}}]}.
    +{engine_id,        "mgrEngine"}.
    +{max_message_size, 484}.

    The value of engine_id is a string, which should have a very specific structure. See RFC 2271/2571 for details.

    And this is a code (snippet) example of how to generate this file in runtime:

    ManagerDir    = "/tmp",
     Port          = 5000,
    -Addr4         = {141,213,11,24},
    -Addr6         = {0,0,0,0,0,0,0,1},
    -Transports    = [{transportDomainUdpIpv4, {Addr4, Port}},
    -                 {transportDomainUdpIpv6, {Addr6, Port}}],
    +Addr4         = {141,213,11,24},
    +Addr6         = {0,0,0,0,0,0,0,1},
    +Transports    = [{transportDomainUdpIpv4, {Addr4, Port}},
    +                 {transportDomainUdpIpv6, {Addr6, Port}}],
     EngineID      = "mgrEngine",
     MMS           = 484,
    -ManagerConfig = [snmpm_conf:manager_entry(transports,       Transports),
    -                 snmpm_conf:manager_entry(engine_id,        EngineID),
    -                 snmpm_conf:manager_entry(max_message_size, MMS)],
    -snmpm_conf:write_manager_config(ManagerDir, ManagerConfig),

    Users

    For each manager user, the manager needs some information. This information is +ManagerConfig = [snmpm_conf:manager_entry(transports, Transports), + snmpm_conf:manager_entry(engine_id, EngineID), + snmpm_conf:manager_entry(max_message_size, MMS)], +snmpm_conf:write_manager_config(ManagerDir, ManagerConfig),

    Users

    For each manager user, the manager needs some information. This information is either added in the users.conf config file or by calling the register_user function in run-time.

    Each row defines a manager user of the manager.

    Each entry is a tuple of size four:

    {UserId, UserMod, UserData, DefaultAgentConfig}.

    • UserId is any term (used to uniquely identify the user).
    • UserMod is the user callback module (atom).
    • UserData is any term (passed on to the user when calling the UserMod.
    • DefaultAgentConfig is a list of default agent config's. These values are used as default values when this user registers agents.

    And this is a code (snippet) example of how to generate this file in runtime:

    ManagerDir         = "/tmp",
    -UserID             = make_ref(),
    +UserID             = make_ref(),
     UserMod            = my_manager_callback_mod,
    -UserData           = self(),
    -DefaultAgentConfig = [{version, v1}, {timeout, 2500}, {max_message_size, 484}],
    -UsersConfig = [snmpm_conf:users_entry(UserID, UserMod, UserData,
    -                                      DefaultAgentConfig)],
    -snmpm_conf:write_users_config(ManagerDir, UsersConfig),

    Agents

    The information needed to handle agents should be stored in a file called +UserData = self(), +DefaultAgentConfig = [{version, v1}, {timeout, 2500}, {max_message_size, 484}], +UsersConfig = [snmpm_conf:users_entry(UserID, UserMod, UserData, + DefaultAgentConfig)], +snmpm_conf:write_users_config(ManagerDir, UsersConfig),

    Agents

    The information needed to handle agents should be stored in a file called agents.conf. It is also possible to add agents in run-time by calling the register_agent.

    Each entry is a tuple:

    {UserId, TargetName, Comm, Domain, Addr, EngineID, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel}.

    • UserId is the identity of the manager user responsible for this agent (term).
    • TargetName is a unique non-empty string.
    • Comm is the community string (string).
    • Domain is the transport domain, either transportDomainUdpIpv4 or @@ -72,23 +72,23 @@ (integer).
    • Version is the version (v1 | v2 | v3).

    • SecModel is the security model (any | v1 | v2c | usm).

    • SecName is the security name (string).
    • SecLevel is security level (noAuthNoPriv | authNoPriv | authPriv).

    Legacy configurations using tuples without Domain element, as well as with all TDomain, Ip and Port elements still work.

    And this is a code (snippet) example of how to generate this file in runtime:

    ManagerDir   = "/tmp",
     UserID       = ...
    -AgentsConfig = [snmpm_conf:agents_entry(UserID,
    +AgentsConfig = [snmpm_conf:agents_entry(UserID,
                                             "target 1",
     					"FOOBAR",
    -					transportDomainUdpIpv4, {{1,2,3,4},161},
    +					transportDomainUdpIpv4, {{1,2,3,4},161},
     					"agent Engine 1"
     					1500,
     					484.
    -					v1, v1, "sec name 1", noAuthNoPriv),
    -		snmpm_conf:agents_entry(UserID,
    +					v1, v1, "sec name 1", noAuthNoPriv),
    +		snmpm_conf:agents_entry(UserID,
                                             "target 2",
     					"FOOBAR",
    -					transportDomainUdpIpv4, {{5,6,7,8},161},
    +					transportDomainUdpIpv4, {{5,6,7,8},161},
     					"agent Engine 2"
     					1500,
     					1000.
    -					v1, v1, "sec name 2", noAuthNoPriv)],
    -snmpm_conf:write_agents_config(ManagerDir, UsersConfig),

    Security data for USM

    The information about Security data for USM should be stored in a file called + v1, v1, "sec name 2", noAuthNoPriv)], +snmpm_conf:write_agents_config(ManagerDir, UsersConfig),

    Security data for USM

    The information about Security data for USM should be stored in a file called usm.conf, which must be present if the manager wishes to use SNMPv3 when communicating with agents. It is also possible to add usm data in run-time by calling the register_usm_user.

    The corresponding table is usmUserTable in the SNMP-USER-BASED-SM-MIB @@ -101,13 +101,13 @@ usmAesCfb128Protocol.

  • PrivKey is a list (of integer). This is the User's secret localized encryption key. It is not visible in the MIB. The length of this key needs to be 16 if usmDESPrivProtocol or usmAesCfb128Protocol is used.

  • ManagerDir = "/tmp",
    -UsmConfig  = [snmpm_conf:usm_entry("engine",
    +UsmConfig  = [snmpm_conf:usm_entry("engine",
                                        "user 1",
     	                           usmNoAuthProtocol,
    -	 			   [],
    +	 			   [],
     	 			   usmNoPrivProtocol,
    -	 			   [])],
    -snmpm_conf:write_usm_config(ManagerDir, UsmConfig),
    + [])], +snmpm_conf:write_usm_config(ManagerDir, UsmConfig),
    /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_mib_compiler.xhtml differs (HTML document, ASCII text, with very long lines (1052)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_mib_compiler.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_mib_compiler.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -27,16 +27,16 @@ association file, it gives a warning message and uses default instrumentation functions. (See Default Instrumentation for more details).

    The MIB compiler is started with a call to snmpc:compile(<mibname>). For -example:

    snmpc:compile("RFC1213-MIB").

    The output is a new file which is called <mibname>.bin.

    The MIB compiler understands both SMIv1 and SMIv2 MIBs. It uses the +example:

    snmpc:compile("RFC1213-MIB").

    The output is a new file which is called <mibname>.bin.

    The MIB compiler understands both SMIv1 and SMIv2 MIBs. It uses the MODULE-IDENTITY statement to determinate if the MIB is written in SMI version 1 or 2.

    Importing MIBs

    The compiler handles the IMPORT statement. It is important to import the compiled file and not the ASN.1 (source) file. A MIB must be recompiled to make changes visible to other MIBs importing it.

    The compiled files of the imported MIBs must be present in the current directory, or a directory in the current path. The path is supplied with the -{i, Path} option, for example:

    snmpc:compile("MY-MIB",
    -       [{i, ["friend_mibs/", "../standard_mibs/"]}]).

    It is also possible to import MIBs from OTP applications in an "include_lib" -like fashion with the il option. Example:

    snmpc:compile("MY-MIB",
    -       [{il, ["snmp/priv/mibs/", "myapp/priv/mibs/"]}]).

    finds the latest version of the snmp and myapp applications in the OTP +{i, Path} option, for example:

    snmpc:compile("MY-MIB",
    +       [{i, ["friend_mibs/", "../standard_mibs/"]}]).

    It is also possible to import MIBs from OTP applications in an "include_lib" +like fashion with the il option. Example:

    snmpc:compile("MY-MIB",
    +       [{il, ["snmp/priv/mibs/", "myapp/priv/mibs/"]}]).

    finds the latest version of the snmp and myapp applications in the OTP system and uses the expanded paths as include paths.

    Note that an SMIv2 MIB can import an SMIv1 MIB and vice versa.

    The following MIBs are built-ins of the Erlang SNMP compiler: SNMPv2-SMI, RFC-1215, RFC-1212, SNMPv2-TC, SNMPv2-CONF, and RFC1155-SMI. They cannot therefore be compiled separately.

    MIB Consistency Checking

    When an MIB is compiled, the compiler detects if several managed objects use the /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmpm.xhtml differs (HTML document, ASCII text, with very long lines (1951)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmpm.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmpm.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -1886,8 +1886,8 @@

    Load a Mib into the manager. The MibName is the name of the Mib, including -the path to where the compiled mib is found. For example,

              Dir = code:priv_dir(my_app) ++ "/mibs/",
    -          snmpm:load_mib(Dir ++ "MY-MIB").
    +the path to where the compiled mib is found. For example,

              Dir = code:priv_dir(my_app) ++ "/mibs/",
    +          snmpm:load_mib(Dir ++ "MY-MIB").
    @@ -3467,8 +3467,8 @@

    Unload a Mib from the manager. The MibName is the name of the Mib, including -the path to where the compiled mib is found. For example,

              Dir = code:priv_dir(my_app) ++ "/mibs/",
    -          snmpm:unload_mib(Dir ++ "MY-MIB").
    +the path to where the compiled mib is found. For example,

              Dir = code:priv_dir(my_app) ++ "/mibs/",
    +          snmpm:unload_mib(Dir ++ "MY-MIB").
    /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_pdus.xhtml differs (HTML document, ASCII text, with very long lines (395)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_pdus.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp_pdus.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -28,8 +28,8 @@ Erlang record representations and vice versa. The record definitions can be found in the file snmp/include/snmp_types.hrl. If snmpv3 is used, the module that includes snmp_types.hrl must define the constant SNMP_USE_V3 before the -header file is included. Example:

    -define(SNMP_USE_V3, true).
    --include_lib("snmp/include/snmp_types.hrl").

    Encoding and decoding must be done explicitly when writing your own Net if +header file is included. Example:

    -define(SNMP_USE_V3, true).
    +-include_lib("snmp/include/snmp_types.hrl").

    Encoding and decoding must be done explicitly when writing your own Net if process.

    /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp.xhtml differs (HTML document, ASCII text, with very long lines (382)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.epub/OEBPS/snmp.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -3214,8 +3214,8 @@

    Utility function(s) to produce a formatted printout of the versions info -generated by the versions1 function

    This is the same as doing, e.g.:

               {ok, V} = snmp:versions1(),
    -           snmp:print_versions(V).
    +generated by the versions1 function

    This is the same as doing, e.g.:

               {ok, V} = snmp:versions1(),
    +           snmp:print_versions(V).
    @@ -3413,17 +3413,17 @@

    This function is used to set up trace on function(s) for the given module or modules.

    The example below sets up trace on the exported functions (default) of module snmp_generic and all functions of module snmp_generic_mnesia. With return -values (which is default) and timestamps in both cases (which is also default):

    	  snmp:enable_trace(),
    -	  snmp:set_trace([snmp_generic,
    -                          {snmp_generic_mnesia, [{scope, all_functions}]}]),
    +values (which is default) and timestamps in both cases (which is also default):

    	  snmp:enable_trace(),
    +	  snmp:set_trace([snmp_generic,
    +                          {snmp_generic_mnesia, [{scope, all_functions}]}]),
     	  .
     	  .
     	  .
    -          snmp:set_trace(snmp_generic, disable),
    +          snmp:set_trace(snmp_generic, disable),
     	  .
     	  .
     	  .
    -	  snmp:disable_trace(),
    +
    snmp:disable_trace(),
    /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.html 2026-08-21 04:00:27.469347137 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp.html 2026-08-21 04:00:27.469347137 +0000 @@ -3301,8 +3301,8 @@

    Utility function(s) to produce a formatted printout of the versions info -generated by the versions1 function

    This is the same as doing, e.g.:

               {ok, V} = snmp:versions1(),
    -           snmp:print_versions(V).
    +generated by the versions1 function

    This is the same as doing, e.g.:

               {ok, V} = snmp:versions1(),
    +           snmp:print_versions(V).
    @@ -3500,17 +3500,17 @@

    This function is used to set up trace on function(s) for the given module or modules.

    The example below sets up trace on the exported functions (default) of module snmp_generic and all functions of module snmp_generic_mnesia. With return -values (which is default) and timestamps in both cases (which is also default):

    	  snmp:enable_trace(),
    -	  snmp:set_trace([snmp_generic,
    -                          {snmp_generic_mnesia, [{scope, all_functions}]}]),
    +values (which is default) and timestamps in both cases (which is also default):

    	  snmp:enable_trace(),
    +	  snmp:set_trace([snmp_generic,
    +                          {snmp_generic_mnesia, [{scope, all_functions}]}]),
     	  .
     	  .
     	  .
    -          snmp:set_trace(snmp_generic, disable),
    +          snmp:set_trace(snmp_generic, disable),
     	  .
     	  .
     	  .
    -	  snmp:disable_trace(),
    +
    snmp:disable_trace(),
    /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_advanced_agent.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1146)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_advanced_agent.html 2026-08-21 04:00:27.492347287 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_advanced_agent.html 2026-08-21 04:00:27.492347287 +0000 @@ -221,48 +221,48 @@ empName DisplayString, empTelNo DisplayString, empStatus RowStatus - }

    The corresponding Mnesia table is specified as follows:

    mnesia:create_table([{name, employees},
    -                     {snmp, [{key, {integer, string}}]},
    -                     {attributes, [key, telno, row_status]}]).

    Note

    In the Mnesia tables, the two key columns are stored as a tuple with two -elements. Therefore, the arity of the table is 3.

    Instrumentation Functions

    The MIB table shown in the previous section can be compiled as follows:

    1> snmpc:compile("EmpMIB", [{db, mnesia}]).

    This is all that has to be done! Now the manager can read, add, and modify + }

    The corresponding Mnesia table is specified as follows:

    mnesia:create_table([{name, employees},
    +                     {snmp, [{key, {integer, string}}]},
    +                     {attributes, [key, telno, row_status]}]).

    Note

    In the Mnesia tables, the two key columns are stored as a tuple with two +elements. Therefore, the arity of the table is 3.

    Instrumentation Functions

    The MIB table shown in the previous section can be compiled as follows:

    1> snmpc:compile("EmpMIB", [{db, mnesia}]).

    This is all that has to be done! Now the manager can read, add, and modify rows. Also, you can use the ordinary Mnesia API to access the table from your programs. The only explicit action is to create the Mnesia table, an action the user has to perform in order to create the required table schemas.

    Adding Own Actions

    It is often necessary to take some specific action when a table is modified. This is accomplished with an instrumentation function. It executes some specific code when the table is set, and passes all other requests down to the -pre-defined function.

    The following example illustrates this idea:

    emp_table(set, RowIndex, Cols) ->
    -    notify_internal_resources(RowIndex, Cols),
    -    snmp_generic:table_func(set, RowIndex, Cols, {empTable, mnesia});
    -emp_table(Op, RowIndex, Cols) ->
    -    snmp_generic:table_func(Op, RowIndex, Cols, {empTable, mnesia}).

    The default instrumentation functions are defined in the module snmp_generic. +pre-defined function.

    The following example illustrates this idea:

    emp_table(set, RowIndex, Cols) ->
    +    notify_internal_resources(RowIndex, Cols),
    +    snmp_generic:table_func(set, RowIndex, Cols, {empTable, mnesia});
    +emp_table(Op, RowIndex, Cols) ->
    +    snmp_generic:table_func(Op, RowIndex, Cols, {empTable, mnesia}).

    The default instrumentation functions are defined in the module snmp_generic. Refer to the Reference Manual, section SNMP, module snmp_generic for details.

    Extending the Mnesia Table

    A table may contain columns that are used internally, but should not be visible to a manager. These internal columns must be the last columns in the table. The set operation will not work with this arrangement, because there are columns that the agent does not know about. This situation is handled by adding values for the internal columns in the set function.

    To illustrate this, suppose we extend our Mnesia empTable with one internal column. We create it as before, but with an arity of 4, by adding another -attribute.

    mnesia:create_table([{name, employees},
    -                     {snmp, [{key, {integer, string}}]},
    -                     {attributes, {key, telno, row_status, internal_col}}]).

    The last column is the internal column. When performing a set operation, which +attribute.

    mnesia:create_table([{name, employees},
    +                     {snmp, [{key, {integer, string}}]},
    +                     {attributes, {key, telno, row_status, internal_col}}]).

    The last column is the internal column. When performing a set operation, which creates a row, we must give a value to the internal column. The instrumentation -functions will now look as follows:

    -define(createAndGo, 4).
    --define(createAndWait, 5).
    +functions will now look as follows:

    -define(createAndGo, 4).
    +-define(createAndWait, 5).
     
    -emp_table(set, RowIndex, Cols) ->
    -  notify_internal_resources(RowIndex, Cols),
    +emp_table(set, RowIndex, Cols) ->
    +  notify_internal_resources(RowIndex, Cols),
       NewCols =
    -    case is_row_created(empTable, Cols) of
    -      true -> Cols ++ [{4, "internal"}]; % add internal column
    +    case is_row_created(empTable, Cols) of
    +      true -> Cols ++ [{4, "internal"}]; % add internal column
           false -> Cols                      % keep original cols
       end,
    -  snmp_generic:table_func(set, RowIndex, NewCols, {empTable, mnesia});
    -emp_table(Op, RowIndex, Cols) ->
    -  snmp_generic:table_func(Op, RowIndex, Cols, {empTable, mnesia}).
    +  snmp_generic:table_func(set, RowIndex, NewCols, {empTable, mnesia});
    +emp_table(Op, RowIndex, Cols) ->
    +  snmp_generic:table_func(Op, RowIndex, Cols, {empTable, mnesia}).
     
    -is_row_created(Name, Cols) ->
    -  case snmp_generic:get_status_col(Name, Cols) of
    -    {ok, ?createAndGo} -> true;
    -    {ok, ?createAndWait} -> true;
    +is_row_created(Name, Cols) ->
    +  case snmp_generic:get_status_col(Name, Cols) of
    +    {ok, ?createAndGo} -> true;
    +    {ok, ?createAndWait} -> true;
         _ -> false
       end.

    If a row is created, we always set the internal column to "internal".

    Deviations from the Standard

    In some aspects the agent does not implement SNMP fully. Here are the differences:

    • The default functions and snmp_generic cannot handle an object of type /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_agent_config_files.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1549)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_agent_config_files.html 2026-08-21 04:00:27.516347443 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_agent_config_files.html 2026-08-21 04:00:27.518347456 +0000 @@ -108,30 +108,30 @@ config_err/2 of the error report module at start-up.

      Agent Information

      The agent information should be stored in a file called agent.conf.

      Each entry is a tuple of size two:

      {AgentVariable, Value}.

      • AgentVariable is one of the variables in SNMP-FRAMEWORK-MIB or one of the internal variables intAgentUDPPort, which defines which UDP port the agent listens to, or intAgentTransports, which defines the transport domains and -addresses of the agent.
      • Value is the value for the variable.

      The following example shows an agent.conf file:

      {intAgentUDPPort, 4000}.
      -{intAgentTransports,
      - [{transportDomainUdpIpv4, {141,213,11,24}},
      -  {transportDomainUdpIpv6, {0,0,0,0,0,0,0,1}}]}.
      -{snmpEngineID, "mbj's engine"}.
      -{snmpEngineMaxMessageSize, 484}.

      And this is a code (snippet) example of how to generate this file in runtime:

      AgentDir    = "/tmp",
      +addresses of the agent.
    • Value is the value for the variable.

    The following example shows an agent.conf file:

    {intAgentUDPPort, 4000}.
    +{intAgentTransports,
    + [{transportDomainUdpIpv4, {141,213,11,24}},
    +  {transportDomainUdpIpv6, {0,0,0,0,0,0,0,1}}]}.
    +{snmpEngineID, "mbj's engine"}.
    +{snmpEngineMaxMessageSize, 484}.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir    = "/tmp",
     AgentPort   = 4000,
    -Transports  = [{transportDomainUdpIpv4, {141,213,11,24}},
    -               {transportDomainUdpIpv6, {0,0,0,0,0,0,0,1}}],
    +Transports  = [{transportDomainUdpIpv4, {141,213,11,24}},
    +               {transportDomainUdpIpv6, {0,0,0,0,0,0,0,1}}],
     EngineID    = "mbj's engine",
     MMS         = 484,
     AgentConfig =
    -   [snmpa_conf:agent_entry(intAgentUDPPort,          AgentPort),
    -    snmpa_conf:agent_entry(intAgentTransports,       Transports),
    -    snmpa_conf:agent_entry(snmpEngineID,             EngineID),
    -    snmpa_conf:agent_entry(snmpEngineMaxMessageSize, MMS)],
    -snmpa_conf:write_agent_config(AgentDir, AgentConfig),

    These are the supported entries and their value types:

          {snmpEngine,               string()}.                     % Mandatory
    -      {snmpEngineMaxMessageSize, snmp_framework_mib:max_message_size()}.  % Mandatory
    -      {intAgentUDPPort,          inet:port_number()}.                      % Optional
    -      {intAgentTransports,       [snmpa_conf:intAgentTransport()]}.   % Mandatory

    If a "traditional" transport is specified (without explicit Kind, handling + [snmpa_conf:agent_entry(intAgentUDPPort, AgentPort), + snmpa_conf:agent_entry(intAgentTransports, Transports), + snmpa_conf:agent_entry(snmpEngineID, EngineID), + snmpa_conf:agent_entry(snmpEngineMaxMessageSize, MMS)], +snmpa_conf:write_agent_config(AgentDir, AgentConfig),

    These are the supported entries and their value types:

          {snmpEngine,               string()}.                     % Mandatory
    +      {snmpEngineMaxMessageSize, snmp_framework_mib:max_message_size()}.  % Mandatory
    +      {intAgentUDPPort,          inet:port_number()}.                      % Optional
    +      {intAgentTransports,       [snmpa_conf:intAgentTransport()]}.   % Mandatory

    If a "traditional" transport is specified (without explicit Kind, handling both requests and traps) for a transport domain, its not possible to also specify a transport (for that domain) with a specific Kind. This is for -example, not allowed:

     [{transportDomainUdpIpv4, {{141,213,11,24}, 4000}},
    -  {transportDomainUdpIpv4, {{141,213,11,24}, 4001}, trap_sender}].

    Note that only one transport per kind for each transport domain can be +example, not allowed:

     [{transportDomainUdpIpv4, {{141,213,11,24}, 4000}},
    +  {transportDomainUdpIpv4, {{141,213,11,24}, 4001}, trap_sender}].

    Note that only one transport per kind for each transport domain can be configured.

    PortInfo system is used to indicate that the 'system' should choose (the way port number '0' (zero) is normally used). Port info '0' (zero) cannot be used for this, since it is (internally) used to represent the 'default' port number.

    In the traditional transport entries, when the Addr value does not contain a @@ -146,32 +146,32 @@ default context "" need not be present.

    Each row defines a context in the agent. This information is used in the table vacmContextTable in the SNMP-VIEW-BASED-ACM-MIB.

    Each entry is a term:

    ContextName.

    • ContextName is a string.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir      = "/tmp",
     ContextConfig =
    -   [snmpa_conf:context_entry("foo"),
    -    snmpa_conf:context_entry("bar")],
    -snmpa_conf:write_context_config(AgentDir, ContextConfig),

    System Information

    The system information should be stored in a file called standard.conf.

    Each entry is a tuple of size two:

    {SystemVariable, Value}.

    • SystemVariable is one of the variables in the system group, or -snmpEnableAuthenTraps.
    • Value is the value for the variable.

    The following example shows a valid standard.conf file:

    {sysDescr, "Erlang SNMP agent"}.
    -{sysObjectID, [1,2,3]}.
    -{sysContact, "(mbj,eklas)@erlang.ericsson.se"}.
    -{sysName, "test"}.
    -{sysServices, 72}.
    -{snmpEnableAuthenTraps, enabled}.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir  = "/tmp",
    +   [snmpa_conf:context_entry("foo"),
    +    snmpa_conf:context_entry("bar")],
    +snmpa_conf:write_context_config(AgentDir, ContextConfig),

    System Information

    The system information should be stored in a file called standard.conf.

    Each entry is a tuple of size two:

    {SystemVariable, Value}.

    • SystemVariable is one of the variables in the system group, or +snmpEnableAuthenTraps.
    • Value is the value for the variable.

    The following example shows a valid standard.conf file:

    {sysDescr, "Erlang SNMP agent"}.
    +{sysObjectID, [1,2,3]}.
    +{sysContact, "(mbj,eklas)@erlang.ericsson.se"}.
    +{sysName, "test"}.
    +{sysServices, 72}.
    +{snmpEnableAuthenTraps, enabled}.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir  = "/tmp",
     StdConfig =
    -   [snmpa_conf:standard_entry(sysDescr,    "Erlang SNMP agent"),
    -    snmpa_conf:standard_entry(sysObjectID, [1,2,3]),
    -    snmpa_conf:standard_entry(sysContact,  "(mbj,eklas)@erlang.ericsson.se"),
    -    snmpa_conf:standard_entry(sysName,     "test"),
    -    snmpa_conf:standard_entry(sysServices, 72),
    -    snmpa_conf:standard_entry(snmpEnableAuthenTraps, enabled)],
    -snmpa_conf:write_standard_config(AgentDir, StdConfig),

    A value must be provided for all variables, which lack default values in the + [snmpa_conf:standard_entry(sysDescr, "Erlang SNMP agent"), + snmpa_conf:standard_entry(sysObjectID, [1,2,3]), + snmpa_conf:standard_entry(sysContact, "(mbj,eklas)@erlang.ericsson.se"), + snmpa_conf:standard_entry(sysName, "test"), + snmpa_conf:standard_entry(sysServices, 72), + snmpa_conf:standard_entry(snmpEnableAuthenTraps, enabled)], +snmpa_conf:write_standard_config(AgentDir, StdConfig),

    A value must be provided for all variables, which lack default values in the MIB.

    Communities

    The community information should be stored in a file called community.conf. It must be present if the agent is configured for SNMPv1 or SNMPv2c.

    An SNMP community is a relationship between an SNMP agent and a set of SNMP managers that defines authentication, access control and proxy characteristics.

    The corresponding table is snmpCommunityTable in the SNMP-COMMUNITY-MIB.

    Each entry is a term:

    {CommunityIndex, CommunityName, SecurityName, ContextName, TransportTag}.

    • CommunityIndex is a non-empty string.
    • CommunityName is a string.
    • SecurityName is a string.
    • ContextName is a string.
    • TransportTag is a string.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir        = "/tmp",
     CommunityConfig =
    -   [snmpa_conf:community_entry("public"),
    -    snmpa_conf:community_entry("all-rights"),
    -    snmpa_conf:community_entry("standard trap",
    -                               "standard trap", "initial", "", "")],
    -snmpa_conf:write_community_config(AgentDir, CommunityConfig),

    MIB Views for VACM

    The information about MIB Views for VACM should be stored in a file called + [snmpa_conf:community_entry("public"), + snmpa_conf:community_entry("all-rights"), + snmpa_conf:community_entry("standard trap", + "standard trap", "initial", "", "")], +snmpa_conf:write_community_config(AgentDir, CommunityConfig),

    MIB Views for VACM

    The information about MIB Views for VACM should be stored in a file called vacm.conf.

    The corresponding tables are vacmSecurityToGroupTable, vacmAccessTable and vacmViewTreeFamilyTable in the SNMP-VIEW-BASED-ACM-MIB.

    Each entry is one of the terms, one entry corresponds to one row in one of the tables.

    {vacmSecurityToGroup, SecModel, SecName, GroupName}.

    {vacmAccess, GroupName, Prefix, SecModel, SecLevel, Match, ReadView, WriteView, NotifyView}.

    {vacmViewTreeFamily, ViewIndex, ViewSubtree, ViewStatus, ViewMask}.

    • SecModel is any, v1, v2c, or usm.
    • SecName is a string.
    • GroupName is a string.
    • Prefix is a string.
    • SecLevel is noAuthNoPriv, authNoPriv, or authPriv
    • Match is prefix or exact.
    • ReadView is a string.
    • WriteView is a string.
    • NotifyView is a string.
    • ViewIndex is an integer.
    • ViewSubtree is a list of integer.
    • ViewStatus is either included or excluded
    • ViewMask is either null or a list of ones and zeros. Ones nominate that an @@ -180,17 +180,17 @@ regarded as all ones. null is shorthand for a mask with all ones.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir   = "/tmp",
     SecName    = "plain",
     VacmConfig =
    -   [%%                        SecModel, SecName, GroupName
    -    snmpa_conf:vacm_s2g_entry(usm, SecName, SecName),
    +   [%%                        SecModel, SecName, GroupName
    +    snmpa_conf:vacm_s2g_entry(usm, SecName, SecName),
     
         %%                        GroupName, Prefix, SecModel,
    -    snmpa_conf:vacm_acc_entry(SecName, "", any,
    +    snmpa_conf:vacm_acc_entry(SecName, "", any,
         %%                        SecLevel, Match, RV, WV, NV
    -                              noAuthNoPriv, exact, "all", "all", "all"),
    +                              noAuthNoPriv, exact, "all", "all", "all"),
     
         %%                        ViewName, ViewSubtree, ViewType, ViewMask
    -    snmpa_conf:vacm_vtf_entry("restricted", [1,3,6,1], included, null)],
    -snmpa_conf:write_vacm_config(AgentDir, VacmConfig),

    Security data for USM

    The information about Security data for USM should be stored in a file called + snmpa_conf:vacm_vtf_entry("restricted", [1,3,6,1], included, null)], +snmpa_conf:write_vacm_config(AgentDir, VacmConfig),

    Security data for USM

    The information about Security data for USM should be stored in a file called usm.conf, which must be present if the agent is configured for SNMPv3.

    The corresponding table is usmUserTable in the SNMP-USER-BASED-SM-MIB (adjusted according to SNMP-USM-HMAC-SHA2-MIB).

    Each entry is a term:

    {EngineID, UserName, SecName, Clone, AuthP, AuthKeyC, OwnAuthKeyC, PrivP, PrivKeyC, OwnPrivKeyC, Public, AuthKey, PrivKey}.

    • EngineID is a string.

    • UserName is a string.

    • SecName is a string.

    • Clone is zeroDotZero or a list of integers.

    • AuthP is a usmNoAuthProtocol, usmHMACMD5AuthProtocol, usmHMACSHAAuthProtocol, usmHMAC128SHA224AuthProtocol, @@ -203,29 +203,29 @@ be 16 if usmDESPrivProtocol or usmAesCfb128Protocol is used.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir  = "/tmp",
     EngineID  = "plain engine"
     Passwd    = "FooBar Hoopla", %% This should *obviously* be choosen better
    -Secret16  = snmp:passwd2localized_key(md5, Passwd, EngineID),
    -Secret20  = snmp:passwd2localized_key(sha, Passwd, EngineID),
    +Secret16  = snmp:passwd2localized_key(md5, Passwd, EngineID),
    +Secret20  = snmp:passwd2localized_key(sha, Passwd, EngineID),
     UsmConfig =
    -   [snmpa_conf:usm_entry(EngineID, "initial", "initial", zeroDotZero,
    +   [snmpa_conf:usm_entry(EngineID, "initial", "initial", zeroDotZero,
                              usmHMACMD5AuthProtocol, "", "",
                              usmNoPrivProtocol, "", "",
    -                         "", Secret16, ""),
    +                         "", Secret16, ""),
     
    -    snmpa_conf:usm_entry(EngineID, "templateMD5", "templateMD5", zeroDotZero,
    +    snmpa_conf:usm_entry(EngineID, "templateMD5", "templateMD5", zeroDotZero,
                              usmHMACMD5AuthProtocol, "", "",
                              usmDESPrivProtocol, "", "",
    -                         "", Secret16, Secret16),
    +                         "", Secret16, Secret16),
     
    -    snmpa_conf:usm_entry(EngineID, "templateSHA", "templateSHA", zeroDotZero,
    +    snmpa_conf:usm_entry(EngineID, "templateSHA", "templateSHA", zeroDotZero,
                              usmHMACSHAAuthProtocol, "", "",
                              usmAesCfb128Protocol, "", "",
    -                         "", Secret20, Secret16)],
    -snmpa_conf:write_usm_config(AgentDir, UsmConfig),

    Notify Definitions

    The information about Notify Definitions should be stored in a file called + "", Secret20, Secret16)], +snmpa_conf:write_usm_config(AgentDir, UsmConfig),

    Notify Definitions

    The information about Notify Definitions should be stored in a file called notify.conf.

    The corresponding table is snmpNotifyTable in the SNMP-NOTIFICATION-MIB.

    Each entry is a term:

    {NotifyName, Tag, Type}.

    • NotifyName is a unique non-empty string.
    • Tag is a string.
    • Type is trap or inform.

    And this is a code (snippet) example of how to generate this file in runtime:

    AgentDir     = "/tmp",
     NotifyConfig =
    -   [snmpa_conf:notify_entry("standard trap",   "std_trap",   trap),
    -    snmpa_conf:notify_entry("standard inform", "std_inform", inform)],
    -snmpa_conf:write_notify_config(AgentDir, NotifyConfig),

    Target Address Definitions

    The information about Target Address Definitions should be stored in a file + [snmpa_conf:notify_entry("standard trap", "std_trap", trap), + snmpa_conf:notify_entry("standard inform", "std_inform", inform)], +snmpa_conf:write_notify_config(AgentDir, NotifyConfig),

    Target Address Definitions

    The information about Target Address Definitions should be stored in a file called target_addr.conf.

    The corresponding tables are snmpTargetAddrTable in the SNMP-TARGET-MIB and snmpTargetAddrExtTable in the SNMP-COMMUNITY-MIB.

    Each entry is a term:

    {TargetName, Domain, Addr, Timeout, RetryCount, TagList, ParamsName, EngineId}.
    or
    {TargetName, Domain, Addr, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}.

    • TargetName is a unique non-empty string.

    • Domain is one of the atoms: transportDomainUdpIpv4 | transportDomainUdpIpv6.

    • Addr is either an IpAddr or an {IpAddr, IpPort} tuple. IpAddr is @@ -236,12 +236,12 @@ configurations still work.

      Note that if EngineId has the value discovery, the agent cannot send inform messages to that manager until it has performed the discovery process with that manager.

      And this is a code (snippet) example of how to generate this file in runtime:

      AgentDir         = "/tmp",
      -Addr1            = {{1,2,3,4},     162},
      -Addr2            = {{11,21,31,41}, 162},
      +Addr1            = {{1,2,3,4},     162},
      +Addr2            = {{11,21,31,41}, 162},
       Timeout          = 1500,
       RetryCount       = 3,
       TargetAddrConfig =
      -   [snmpa_conf:target_addr_entry("Target 1",
      +   [snmpa_conf:target_addr_entry("Target 1",
                                        transportDomainUdpIpv4, Addr1,
       				 Timeout, RetryCount,
       				 "std_trap, "target_1", "",
      @@ -250,13 +250,13 @@
                                        transportDomainUdpIpv4, Addr2,
       				 Timeout, RetryCount,
       				 "std_inform, "target_2", "",
      -				 [], 2048)],
      -snmpa_conf:write_target_addr_config(AgentDir, TargetAddrConfig),

      Target Parameters Definitions

      The information about Target Parameters Definitions should be stored in a file + [], 2048)], +snmpa_conf:write_target_addr_config(AgentDir, TargetAddrConfig),

      Target Parameters Definitions

      The information about Target Parameters Definitions should be stored in a file called target_params.conf.

      The corresponding table is snmpTargetParamsTable in the SNMP-TARGET-MIB.

      Each entry is a term:

      {ParamsName, MPModel, SecurityModel, SecurityName, SecurityLevel}.

      • ParamsName is a unique non-empty string.
      • MPModel is v1, v2c or v3
      • SecurityModel is v1, v2c, or usm.
      • SecurityName is a string.
      • SecurityLevel is noAuthNoPriv, authNoPriv or authPriv.

      And this is a code (snippet) example of how to generate this file in runtime:

      AgentDir         = "/tmp",
       TargetAddrConfig =
      -   [snmpa_conf:target_params_entry("target_1", v1),
      -    snmpa_conf:target_params_entry("target_2", v2, "initial", noAthNoPriv],
      -snmpa_conf:write_target_params_config(AgentDir, TargetParamsConfig),
      /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_agent_funct_descr.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (773)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_agent_funct_descr.html 2026-08-21 04:00:27.543347619 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_agent_funct_descr.html 2026-08-21 04:00:27.543347619 +0000 @@ -236,7 +236,7 @@ MIBs are always available in all contexts.

      The ASN.1 code, the Erlang source code, and the generated .hrl files for them are provided in the distribution and are placed in the directories mibs, src, and include, respectively, in the snmp application.

      The .hrl files are generated with snmpc:mib_to_hrl/1. Include these files in -your code as in the following example:

      -include_lib("snmp/include/SNMPv2-MIB.hrl").

      The initial values for the managed objects defined in these tables, are read at +your code as in the following example:

      -include_lib("snmp/include/SNMPv2-MIB.hrl").

      The initial values for the managed objects defined in these tables, are read at start-up from a set of configuration files. These are described in Configuration Files.

      STANDARD-MIB and SNMPv2-MIB

      These MIBs contain the snmp- and system groups from MIB-II which is defined in RFC1213 (STANDARD-MIB) or RFC1907 (SNMPv2-MIB). They are implemented in the @@ -349,9 +349,9 @@ objects in this MIB are now obsolete.

      Notifications

      Notifications are defined in SMIv1 with the TRAP-TYPE macro in the definition of an MIB (see RFC1215). The corresponding macro in SMIv2 is NOTIFICATION-TYPE. When an application decides to send a notification, it calls one of the -following functions:

      snmpa:send_notification(Agent, Notification, Receiver
      -                       [, NotifyName, ContextName, Varbinds])
      -snmpa:send_trap(Agent, Notification, Community [, Receiver, Varbinds])

      providing the registered name or process identifier of the agent where the MIB, +following functions:

      snmpa:send_notification(Agent, Notification, Receiver
      +                       [, NotifyName, ContextName, Varbinds])
      +snmpa:send_trap(Agent, Notification, Community [, Receiver, Varbinds])

      providing the registered name or process identifier of the agent where the MIB, which defines the notification is loaded and the symbolic name of the notification.

      If the send_notification/3,4 function is used, all management targets are selected, as defined in RFC2273. The Receiver parameter defines where the /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_app.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (984)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_app.html 2026-08-21 04:00:27.572347808 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_app.html 2026-08-21 04:00:27.571347801 +0000 @@ -92,51 +92,51 @@

      Description

      This chapter describes the snmp application in OTP. The SNMP application provides the following services:

      • a multilingual extensible SNMP agent
      • a SNMP manager
      • a MIB compiler

      Configuration

      The following configuration parameters are defined for the SNMP application. Refer to application(3) for more information about configuration parameters.

      The snmp part of the config file specifying the configuration parameters is -basically the following tuple:

            {snmp, snmp_components_config()}

      A minimal config file for starting a node with both a manager and an agent:

            [{snmp,
      -        [{agent, [{db_dir, "/tmp/snmp/agent/db"},
      -                  {config, [{dir, "/tmp/snmp/agent/conf"}]}]},
      -         {manager, [{config, [{dir, "/tmp/snmp/manager/conf"},
      -                              {db_dir, "/tmp/snmp/manager/db"}]}]}]}
      -        ]
      +basically the following tuple:

            {snmp, snmp_components_config()}

      A minimal config file for starting a node with both a manager and an agent:

            [{snmp,
      +        [{agent, [{db_dir, "/tmp/snmp/agent/db"},
      +                  {config, [{dir, "/tmp/snmp/agent/conf"}]}]},
      +         {manager, [{config, [{dir, "/tmp/snmp/manager/conf"},
      +                              {db_dir, "/tmp/snmp/manager/db"}]}]}]}
      +        ]
              }
             ].

      Each snmp component has its own set of configuration parameters, even though -some of the types are common to both components.

            snmp_components_config() -> [snmp_component_config()]
      -      snmp_component_config() -> {agent, agent_options()} | {manager, manager_options()}
      -      agent_options() = [agent_option()]
      -      agent_option() = {restart_type,     restart_type()}     |
      -                       {agent_type,       agent_type()}       |
      -                       {agent_verbosity,  verbosity()}        |
      -                       {discovery,        agent_discovery()}  |
      -                       {versions,         versions()}         |
      -                       {gb_max_vbs,       gb_max_vbs()}       |
      -                       {priority,         priority()}         |
      -                       {multi_threaded,   multi_threaded()}   |
      -                       {db_dir,           db_dir()}           |
      -                       {db_init_error,    db_init_error()}    |
      -                       {local_db,         local_db()}         |
      -                       {net_if,           agent_net_if()}     |
      -                       {mibs,             mibs()}             |
      -                       {mib_storage,      mib_storage()}      |
      -                       {mib_server,       mib_server()}       |
      -                       {audit_trail_log,  audit_trail_log()}  |
      -                       {error_report_mod, error_report_mod()} |
      -                       {note_store,       note_store()}       |
      -                       {symbolic_store,   symbolic_store()}   |
      -                       {target_cache,     target_cache()}     |
      -                       {config,           agent_config()}
      -      manager_options() = [manager_option()]
      -      manager_option() = {restart_type,             restart_type()}    |
      -                         {net_if,                   manager_net_if()}  |
      -                         {server,                   server()}          |
      -                         {note_store,               note_store()}      |
      -                         {config,                   manager_config()}  |
      -                         {inform_request_behaviour, manager_irb()}     |
      -                         {mibs,                     manager_mibs()}    |
      -                         {priority,                 priority()}        |
      -                         {audit_trail_log,          audit_trail_log()} |
      -                         {versions,                 versions()}        |
      -                         {def_user_mod,             def_user_module()  |
      -                         {def_user_data,            def_user_data()}

      Agent specific config options and types:

      • agent_type() = master | sub <optional> - If master, +some of the types are common to both components.

              snmp_components_config() -> [snmp_component_config()]
        +      snmp_component_config() -> {agent, agent_options()} | {manager, manager_options()}
        +      agent_options() = [agent_option()]
        +      agent_option() = {restart_type,     restart_type()}     |
        +                       {agent_type,       agent_type()}       |
        +                       {agent_verbosity,  verbosity()}        |
        +                       {discovery,        agent_discovery()}  |
        +                       {versions,         versions()}         |
        +                       {gb_max_vbs,       gb_max_vbs()}       |
        +                       {priority,         priority()}         |
        +                       {multi_threaded,   multi_threaded()}   |
        +                       {db_dir,           db_dir()}           |
        +                       {db_init_error,    db_init_error()}    |
        +                       {local_db,         local_db()}         |
        +                       {net_if,           agent_net_if()}     |
        +                       {mibs,             mibs()}             |
        +                       {mib_storage,      mib_storage()}      |
        +                       {mib_server,       mib_server()}       |
        +                       {audit_trail_log,  audit_trail_log()}  |
        +                       {error_report_mod, error_report_mod()} |
        +                       {note_store,       note_store()}       |
        +                       {symbolic_store,   symbolic_store()}   |
        +                       {target_cache,     target_cache()}     |
        +                       {config,           agent_config()}
        +      manager_options() = [manager_option()]
        +      manager_option() = {restart_type,             restart_type()}    |
        +                         {net_if,                   manager_net_if()}  |
        +                         {server,                   server()}          |
        +                         {note_store,               note_store()}      |
        +                         {config,                   manager_config()}  |
        +                         {inform_request_behaviour, manager_irb()}     |
        +                         {mibs,                     manager_mibs()}    |
        +                         {priority,                 priority()}        |
        +                         {audit_trail_log,          audit_trail_log()} |
        +                         {versions,                 versions()}        |
        +                         {def_user_mod,             def_user_module()  |
        +                         {def_user_data,            def_user_data()}

        Agent specific config options and types:

        • agent_type() = master | sub <optional> - If master, one master agent is started. Otherwise, no agents are started.

          Default is master.

        • agent_discovery() = [agent_discovery_opt()] <optional> - agent_discovery_opt() = {terminating, agent_terminating_discovery_opts()} | {originating, agent_originating_discovery_opts()}

          The terminating options effects discovery initiated by a manager.

          The originating options effects discovery initiated by this agent.

          For defaults see the options in agent_discovery_opt().

        • agent_terminating_discovery_opts() = [agent_terminating_discovery_opt()] <optional> - agent_terminating_discovery_opt() = {enable, boolean()} | {stage2, discovery | plain} | {trigger_username, string()}

          These are options effecting discovery terminating in this agent (i.e. /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_app_b.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_app_b.html 2026-08-21 04:00:27.591347931 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_app_b.html 2026-08-21 04:00:27.591347931 +0000 @@ -538,23 +538,23 @@ immediately removed." - SYNTAX INTEGER { + SYNTAX INTEGER { -- the following two values are states: -- these values may be read or written - active(1), - notInService(2), + active(1), + notInService(2), -- the following value is a state: -- this value may be read, but not written - notReady(3), + notReady(3), -- the following three values are -- actions: these values may be written, -- but are never read - createAndGo(4), - createAndWait(5), - destroy(6) - }

      + createAndGo(4), + createAndWait(5), + destroy(6) + } /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_config.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (850)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_config.html 2026-08-21 04:00:27.621348127 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_config.html 2026-08-21 04:00:27.621348127 +0000 @@ -103,41 +103,41 @@ more information).
    • the database directory stores the internal database files.

    The agent and manager uses (application) configuration parameters to find out where these directories are located. The parameters should be defined in an Erlang system configuration file. The following configuration parameters are -defined for the SNMP application:

          agent_options() = [agent_option()]
    -      agent_option() = {restart_type,     restart_type()}     |
    -                       {agent_type,       agent_type()}       |
    -                       {agent_verbosity,  verbosity()}        |
    -                       {versions,         versions()}         |
    -                       {discovery,        agent_discovery()}  |
    -                       {gb_max_vbs,       gb_max_vbs()}       |
    -                       {priority,         priority()}         |
    -                       {multi_threaded,   multi_threaded()}   |
    -                       {db_dir,           db_dir()}           |
    -                       {db_init_error,    db_init_error()}    |
    -                       {local_db,         local_db()}         |
    -                       {net_if,           agent_net_if()}     |
    -                       {mibs,             mibs()}             |
    -                       {mib_storage,      mib_storage()}      |
    -                       {mib_server,       mib_server()}       |
    -                       {audit_trail_log,  audit_trail_log()}  |
    -                       {error_report_mod, error_report_mod()} |
    -                       {note_store,       note_store()}       |
    -                       {symbolic_store,   symbolic_store()}   |
    -                       {target_cache,     target_cache()}     |
    -                       {config,           agent_config()}
    -      manager_options() = [manager_option()]
    -      manager_option() = {restart_type,             restart_type()}    |
    -                         {net_if,                   manager_net_if()}  |
    -                         {server,                   server()}          |
    -                         {note_store,               note_store()}      |
    -                         {config,                   manager_config()}  |
    -                         {inform_request_behaviour, manager_irb()}     |
    -                         {mibs,                     manager_mibs()}    |
    -                         {priority,                 priority()}        |
    -                         {audit_trail_log,          audit_trail_log()} |
    -                         {versions,                 versions()}        |
    -                         {def_user_mod,             def_user_module()  |
    -                         {def_user_data,            def_user_data()}

    Agent specific config options and types:

    • agent_type() = master | sub <optional> - If master, +defined for the SNMP application:

            agent_options() = [agent_option()]
      +      agent_option() = {restart_type,     restart_type()}     |
      +                       {agent_type,       agent_type()}       |
      +                       {agent_verbosity,  verbosity()}        |
      +                       {versions,         versions()}         |
      +                       {discovery,        agent_discovery()}  |
      +                       {gb_max_vbs,       gb_max_vbs()}       |
      +                       {priority,         priority()}         |
      +                       {multi_threaded,   multi_threaded()}   |
      +                       {db_dir,           db_dir()}           |
      +                       {db_init_error,    db_init_error()}    |
      +                       {local_db,         local_db()}         |
      +                       {net_if,           agent_net_if()}     |
      +                       {mibs,             mibs()}             |
      +                       {mib_storage,      mib_storage()}      |
      +                       {mib_server,       mib_server()}       |
      +                       {audit_trail_log,  audit_trail_log()}  |
      +                       {error_report_mod, error_report_mod()} |
      +                       {note_store,       note_store()}       |
      +                       {symbolic_store,   symbolic_store()}   |
      +                       {target_cache,     target_cache()}     |
      +                       {config,           agent_config()}
      +      manager_options() = [manager_option()]
      +      manager_option() = {restart_type,             restart_type()}    |
      +                         {net_if,                   manager_net_if()}  |
      +                         {server,                   server()}          |
      +                         {note_store,               note_store()}      |
      +                         {config,                   manager_config()}  |
      +                         {inform_request_behaviour, manager_irb()}     |
      +                         {mibs,                     manager_mibs()}    |
      +                         {priority,                 priority()}        |
      +                         {audit_trail_log,          audit_trail_log()} |
      +                         {versions,                 versions()}        |
      +                         {def_user_mod,             def_user_module()  |
      +                         {def_user_data,            def_user_data()}

      Agent specific config options and types:

      • agent_type() = master | sub <optional> - If master, one master agent is started. Otherwise, no agents are started.

        Default is master.

      • agent_discovery() = [agent_discovery_opt()] <optional> - agent_discovery_opt() = {terminating, agent_terminating_discovery_opts()} | {originating, agent_originating_discovery_opts()}

        The terminating options effects discovery initiated by a manager.

        The originating options effects discovery initiated by this agent.

        For defaults see the options in agent_discovery_opt().

      • agent_terminating_discovery_opts() = [agent_terminating_discovery_opt()] <optional> - agent_terminating_discovery_opt() = {enable, boolean()} | {stage2, discovery | plain} | {trigger_username, string()}

        These are options effecting discovery terminating in this agent (i.e. @@ -496,34 +496,34 @@ configuration parameters. The verbosity itself has several _levels: silence | info | log | debug | trace. For the lowest verbosity silence, nothing is printed. The higher the verbosity, the -more is printed. Default value is always silence.

        3> snmpa:verbosity(master_agent, log).
        +more is printed. Default value is always silence.

        3> snmpa:verbosity(master_agent, log).
         ok
        -5> snmpa:verbosity(net_if, log).
        +5> snmpa:verbosity(net_if, log).
         ok
         6>
         %% Example of output from the agent when a get-next-request arrives:
         ** SNMP NET-IF LOG:
        -   got packet from {147,12,12,12}:5000
        +   got packet from {147,12,12,12}:5000
         
         ** SNMP NET-IF MPD LOG:
            v1, community: all-rights
         
         ** SNMP NET-IF LOG:
        -   got pdu from {147,12,12,12}:5000 {pdu, 'get-next-request',
        +   got pdu from {147,12,12,12}:5000 {pdu, 'get-next-request',
                                                   62612569,noError,0,
        -                                          [{varbind,[1,1],'NULL','NULL',1}]}
        +                                          [{varbind,[1,1],'NULL','NULL',1}]}
         
         ** SNMP MASTER-AGENT LOG:
        -   apply: snmp_generic,variable_func,[get,{sysDescr,persistent}]
        +   apply: snmp_generic,variable_func,[get,{sysDescr,persistent}]
         
         ** SNMP MASTER-AGENT LOG:
        -   returned: {value,"Erlang SNMP agent"}
        +   returned: {value,"Erlang SNMP agent"}
         
         ** SNMP NET-IF LOG:
        -   reply pdu: {pdu,'get-response',62612569,noError,0,
        -                   [{varbind,[1,3,6,1,2,1,1,1,0],
        +   reply pdu: {pdu,'get-response',62612569,noError,0,
        +                   [{varbind,[1,3,6,1,2,1,1,1,0],
                                      'OCTET STRING',
        -                             "Erlang SNMP agent",1}]}
        +                             "Erlang SNMP agent",1}]}
         
         ** SNMP NET-IF INFO: time in agent: 19711 mysec

        Other useful function(s) for debugging the agent are:

        • snmpa:info/0,1 - info is used to retrieve a list of miscellaneous agent information.

        • snmpa:which_aliasnames/0 - /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_generic.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1850)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_generic.html 2026-08-21 04:00:27.647348296 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_generic.html 2026-08-21 04:00:27.647348296 +0000 @@ -105,9 +105,9 @@ | MIB | +---------------+ | - Association file (associates a MIB object with + Association file (associates a MIB object with | snmp_generic:table_funct - | snmp_generic:variable_func) + | snmp_generic:variable_func) +--------------------------------------+ | snmp_generic | Support for get-next, | | RowStatus operations @@ -115,7 +115,7 @@ | snmpa_local_db | Mnesia | Database +--------------+-------+---------------+ | dets | ets | -| (persistent) | | +| (persistent) | | +--------------+-------+

        Each function takes the argument NameDb, which is a tuple {Name, Db}, to identify which database the functions should use. Name is the symbolic name of the managed object as defined in the MIB, and Db is either volatile, @@ -127,35 +127,35 @@ this. Specifically, if variables are stored in Mnesia, the table snmp_variables must be created by the programmer. The record definition for this table is defined in the file snmp/include/snmp_types.hrl.

        If an instrumentation function in the association file for a variable myVar -does not have a name when compiling an MIB, the compiler generates an entry.

        {myVar, {snmp_generic, variable_func, [{myVar, Db]}}.

        And for a table:

        {myTable, {snmp_generic, table_func, [{myTable, Db]}}.

        Example

        The following example shows an implementation of a table which is stored in -Mnesia, but with some checks performed at set-request operations.

        myTable_func(new, NameDb) ->   % pass unchanged
        -  snmp_generic:table_func(new, NameDb).
        +does not have a name when compiling an MIB, the compiler generates an entry.

        {myVar, {snmp_generic, variable_func, [{myVar, Db]}}.

        And for a table:

        {myTable, {snmp_generic, table_func, [{myTable, Db]}}.

        Example

        The following example shows an implementation of a table which is stored in +Mnesia, but with some checks performed at set-request operations.

        myTable_func(new, NameDb) ->   % pass unchanged
        +  snmp_generic:table_func(new, NameDb).
         
        -myTable_func(delete, NameDb) ->   % pass unchanged
        -  snmp_generic:table_func(delete, NameDb).
        +myTable_func(delete, NameDb) ->   % pass unchanged
        +  snmp_generic:table_func(delete, NameDb).
         
         %% change row
        -myTable_func(is_set_ok, RowIndex, Cols, NameDb) ->
        -  case snmp_generic:table_func(is_set_ok, RowIndex,
        -                               Cols, NameDb) of
        -    {noError, 0} ->
        -      myApplication:is_set_ok(RowIndex, Cols);
        +myTable_func(is_set_ok, RowIndex, Cols, NameDb) ->
        +  case snmp_generic:table_func(is_set_ok, RowIndex,
        +                               Cols, NameDb) of
        +    {noError, 0} ->
        +      myApplication:is_set_ok(RowIndex, Cols);
             Err ->
               Err
           end;
         
        -myTable_func(set, RowIndex, Cols, NameDb) ->
        -  case snmp_generic:table_func(set, RowIndex, Cols,
        -                               NameDb),
        -    {noError, 0} ->
        +myTable_func(set, RowIndex, Cols, NameDb) ->
        +  case snmp_generic:table_func(set, RowIndex, Cols,
        +                               NameDb),
        +    {noError, 0} ->
               % Now the row is updated, tell the application
        -      myApplication:update(RowIndex, Cols);
        +      myApplication:update(RowIndex, Cols);
             Err ->
               Err
           end;
         
        -myTable_func(Op, RowIndex, Cols, NameDb) ->   % pass unchanged
        -  snmp_generic:table_func(Op, RowIndex, Cols, NameDb).

        The .funcs file would look like:

        {myTable, {myModule, myTable_func, [{myTable, mnesia}]}}.
        +
        myTable_func(Op, RowIndex, Cols, NameDb) -> % pass unchanged + snmp_generic:table_func(Op, RowIndex, Cols, NameDb).

        The .funcs file would look like:

        {myTable, {myModule, myTable_func, [{myTable, mnesia}]}}.
        /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_impl_example_agent.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1539)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_impl_example_agent.html 2026-08-21 04:00:27.675348478 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_impl_example_agent.html 2026-08-21 04:00:27.675348478 +0000 @@ -182,108 +182,108 @@ the default implementation of it. Recall that MIBs imported by "EX1-MIB.mib" must be present and compiled in the current directory ("./STANDARD-MIB.bin","./RFC1213-MIB.bin") when compiling.

        unix> erl -config ./sys
        -1> application:start(snmp).
        +1> application:start(snmp).
         ok
        -2> snmpc:compile("EX1-MIB").
        +2> snmpc:compile("EX1-MIB").
         No accessfunction for 'friendsTable', using default.
         No accessfunction for 'myName', using default.
        -{ok, "EX1-MIB.bin"}
        -3> snmpa:load_mibs(snmp_master_agent, ["EX1-MIB"]).
        +{ok, "EX1-MIB.bin"}
        +3> snmpa:load_mibs(snmp_master_agent, ["EX1-MIB"]).
         ok

        This MIB is now loaded into the agent, and a manager can ask questions. As an example of this, we start another Erlang system and the simple Erlang manager in -the toolkit:

        1> snmp_test_mgr:start_link([{agent,"dront.ericsson.se"},{community,"all-rights"},
        +the toolkit:

        1> snmp_test_mgr:start_link([{agent,"dront.ericsson.se"},{community,"all-rights"},
          %% making it understand symbolic names: {mibs,["EX1-MIB","STANDARD-MIB"]}]).
        -{ok, <0.89.0>}
        +{ok, <0.89.0>}
         %% a get-next request with one OID.
        -2> snmp_test_mgr:gn([[1,3,6,1,3,7]]).
        +2> snmp_test_mgr:gn([[1,3,6,1,3,7]]).
         ok
         * Got PDU:
        -[myName,0] = []
        +[myName,0] = []
         %% A set-request (now using symbolic names for convenience)
        -3> snmp_test_mgr:s([{[myName,0], "Martin"}]).
        +3> snmp_test_mgr:s([{[myName,0], "Martin"}]).
         ok
         * Got PDU:
        -[myName,0] = "Martin"
        +[myName,0] = "Martin"
         %% Try the same get-next request again
        -4> snmp_test_mgr:gn([[1,3,6,1,3,7]]).
        +4> snmp_test_mgr:gn([[1,3,6,1,3,7]]).
         ok
         * Got PDU:
        -[myName,0] = "Martin"
        +[myName,0] = "Martin"
         %% ... and we got the new value.
         %% you can event do row operations. How to add a row:
        -5> snmp_test_mgr:s([{[fName,0], "Martin"}, {[fAddress,0],"home"}, {[fStatus,0],4}]).
        +5> snmp_test_mgr:s([{[fName,0], "Martin"}, {[fAddress,0],"home"}, {[fStatus,0],4}]).
          %% createAndGo
         ok
         * Got PDU:
        -[fName,0] = "Martin"
        -[fAddress,0] = "home"
        -[fStatus,0] = 4
        -6> snmp_test_mgr:gn([[myName,0]]).
        +[fName,0] = "Martin"
        +[fAddress,0] = "home"
        +[fStatus,0] = 4
        +6> snmp_test_mgr:gn([[myName,0]]).
         ok
         * Got PDU:
        -[fName,0] = "Martin"
        -7> snmp_test_mgr:gn().
        +[fName,0] = "Martin"
        +7> snmp_test_mgr:gn().
         ok
         * Got PDU:
        -[fAddress,0] = "home"
        -8> snmp_test_mgr:gn().
        +[fAddress,0] = "home"
        +8> snmp_test_mgr:gn().
         ok
         * Got PDU:
        -[fStatus,0] = 1
        +[fStatus,0] = 1
         9>

        Manual Implementation

        The following example shows a "manual" implementation of the EX1-MIB in Erlang. In this example, the values of the objects are stored in an Erlang server. The server has a 2-tuple as loop data, where the first element is the value of variable myName, and the second is a sorted list of rows in the table friendsTable. Each row is a 4-tuple.

        Note

        There are more efficient ways to create tables manually, i.e. to use the -module snmp_index.

        Code

        -module(ex1).
        --author('dummy@flop.org').
        +module snmp_index.

        Code

        -module(ex1).
        +-author('dummy@flop.org').
         %% External exports
        --export([start/0, my_name/1, my_name/2, friends_table/3]).
        +-export([start/0, my_name/1, my_name/2, friends_table/3]).
         %% Internal exports
        --export([init/0]).
        --define(status_col, 4).
        --define(active, 1).
        --define(notInService, 2).
        --define(notReady, 3).
        --define(createAndGo, 4).   % Action; written, not read
        --define(createAndWait, 5). % Action; written, not read
        --define(destroy, 6).       % Action; written, not read
        -start() ->
        -    spawn(ex1, init, []).
        +-export([init/0]).
        +-define(status_col, 4).
        +-define(active, 1).
        +-define(notInService, 2).
        +-define(notReady, 3).
        +-define(createAndGo, 4).   % Action; written, not read
        +-define(createAndWait, 5). % Action; written, not read
        +-define(destroy, 6).       % Action; written, not read
        +start() ->
        +    spawn(ex1, init, []).
         %%----------------------------------------------------------------
         %% Instrumentation function for variable myName.
         %% Returns: (get) {value, Name}
         %%          (set) noError
         %%----------------------------------------------------------------
        -my_name(get) ->
        -    ex1_server ! {self(), get_my_name},
        -    Name = wait_answer(),
        -    {value, Name}.
        -my_name(set, NewName) ->
        -    ex1_server ! {self(), {set_my_name, NewName}},
        +my_name(get) ->
        +    ex1_server ! {self(), get_my_name},
        +    Name = wait_answer(),
        +    {value, Name}.
        +my_name(set, NewName) ->
        +    ex1_server ! {self(), {set_my_name, NewName}},
             noError.
         %%----------------------------------------------------------------
         %% Instrumentation function for table friendsTable.
         %%----------------------------------------------------------------
        -friends_table(get, RowIndex, Cols) ->
        -    case get_row(RowIndex) of
        -   {ok, Row} ->
        -        get_cols(Cols, Row);
        +friends_table(get, RowIndex, Cols) ->
        +    case get_row(RowIndex) of
        +   {ok, Row} ->
        +        get_cols(Cols, Row);
            _  ->
        -        {noValue, noSuchInstance}
        +        {noValue, noSuchInstance}
             end;
        -friends_table(get_next, RowIndex, Cols) ->
        -    case get_next_row(RowIndex) of
        -   {ok, Row} ->
        -        get_next_cols(Cols, Row);
        +friends_table(get_next, RowIndex, Cols) ->
        +    case get_next_row(RowIndex) of
        +   {ok, Row} ->
        +        get_next_cols(Cols, Row);
            _  ->
        -       case get_next_row([]) of
        -     {ok, Row} ->
        +       case get_next_row([]) of
        +     {ok, Row} ->
                  % Get next cols from first row.
        -         NewCols = add_one_to_cols(Cols),
        -         get_next_cols(NewCols, Row);
        +         NewCols = add_one_to_cols(Cols),
        +         get_next_cols(NewCols, Row);
              _  ->
        -        end_of_table(Cols)
        +        end_of_table(Cols)
                 end
             end;
         %%----------------------------------------------------------------
        @@ -294,168 +294,168 @@
         %%    *) Otherwise, error (for simplicity).
         %% Otherwise, row is modified; check that row exists.
         %%----------------------------------------------------------------
        -friends_table(is_set_ok, RowIndex, Cols) ->
        +friends_table(is_set_ok, RowIndex, Cols) ->
             RowExists =
        -   case get_row(RowIndex) of
        -        {ok, _Row} -> true;
        +   case get_row(RowIndex) of
        +        {ok, _Row} -> true;
                _ -> false
            end,
        -    case is_row_status_col_changed(Cols) of
        -   {true, ?destroy} when RowExists == true ->
        -        {noError, 0};
        -   {true, ?createAndGo} when RowExists == false,
        -                                 length(Cols) == 3 ->
        -        {noError, 0};
        -   {true, _} ->
        -       {inconsistentValue, ?status_col};
        +    case is_row_status_col_changed(Cols) of
        +   {true, ?destroy} when RowExists == true ->
        +        {noError, 0};
        +   {true, ?createAndGo} when RowExists == false,
        +                                 length(Cols) == 3 ->
        +        {noError, 0};
        +   {true, _} ->
        +       {inconsistentValue, ?status_col};
            false when RowExists == true ->
        -        {noError, 0};
        +        {noError, 0};
            _ ->
        -        [{Col, _NewVal} | _Cols] = Cols,
        /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_index.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (807))
        --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_index.html	2026-08-21 04:00:27.698348628 +0000
        +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_index.html	2026-08-21 04:00:27.699348634 +0000
        @@ -100,13 +100,13 @@
         actual implementation of the table. The SNMP ordering, that is implementation of
         GET NEXT, is implemented in this module.

        For example, suppose there is an SNMP table, which is best implemented in Erlang as one process per SNMP table row. Suppose further that the INDEX in the SNMP -table is an OCTET STRING. The index structure would be created as follows:

        snmp_index:new(string)

        For each new process we create, we insert an item in an snmp_index structure:

        new_process(Name, SnmpIndex) ->
        -  Pid = start_process(),
        +table is an OCTET STRING. The index structure would be created as follows:

        snmp_index:new(string)

        For each new process we create, we insert an item in an snmp_index structure:

        new_process(Name, SnmpIndex) ->
        +  Pid = start_process(),
           NewSnmpIndex =
        -    snmp_index:insert(SnmpIndex, Name, Pid),
        +    snmp_index:insert(SnmpIndex, Name, Pid),
           <...>

        With this structure, we can now map an OBJECT IDENTIFIER in e.g. a GET NEXT -request, to the correct process:

        get_next_pid(Oid, SnmpIndex) ->
        -  {ok, {_, Pid}} = snmp_index:get_next(SnmpIndex, Oid),
        +request, to the correct process:

        get_next_pid(Oid, SnmpIndex) ->
        +  {ok, {_, Pid}} = snmp_index:get_next(SnmpIndex, Oid),
           Pid.

        Warnings

        Warning

        All API functions that update the index return a NewIndex term. This is for backward compatibility with a previous implementation that used a B+ tree written purely in Erlang for the index. The NewIndex return value /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_instr_functions.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1719)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_instr_functions.html 2026-08-21 04:00:27.719348764 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_instr_functions.html 2026-08-21 04:00:27.719348764 +0000 @@ -105,8 +105,8 @@ operation is translated into a series of calls to get-next.

        Instrumentation Functions

        The following sections describe how the instrumentation functions should be defined in Erlang for the different operations. In the following, RowIndex is a list of key values for the table, and Column is a column number.

        These functions are described in detail in -Definition of Instrumentation Functions.

        New / Delete Operations

        For scalar variables:

        variable_access(new [, ExtraArg1, ...])
        -variable_access(delete [, ExtraArg1, ...])

        For tables:

        table_access(new [, ExtraArg1, ...])
        +Definition of Instrumentation Functions.

        New / Delete Operations

        For scalar variables:

        variable_access(new [, ExtraArg1, ...])
        +variable_access(delete [, ExtraArg1, ...])

        For tables:

        table_access(new [, ExtraArg1, ...])
         table_access(delete [, ExtraArg1, ...])

        These functions are called for each object in an MIB when the MIB is unloaded or loaded, respectively.

        Get Operation

        For scalar variables:

        variable_access(get [, ExtraArg1, ...])

        For tables:

        table_access(get,RowIndex,Cols [,ExtraArg1, ...])

        Cols is a list of Column. The agent will sort incoming variables so that all operations on one row (same index) will be supplied at the same time. The reason @@ -136,9 +136,9 @@ value 1, and [3, 5] is the list of requested columns. The function should now return the lexicographically next elements:

        [{[3, 1, 2], d}, {[5, 1, 2], f}]

        This is illustrated in the following table:

        GetNext from [3,1,1] and [5,1,1].

        The manager now issues the following getNext request:

        getNext{ myTable.myTableEntry.3.2.1,
                  myTable.myTableEntry.5.2.1 }

        This is transformed into one call to my_table:

        my_table(get_next, [2, 1], [3, 5])

        The function should now return:

        [{[4, 1, 1], b}, endOfTable]

        This is illustrated in the following table:

        GetNext from [3,2,1] and [5,2,1].

        The manager now issues the following getNext request:

        getNext{ myTable.myTableEntry.3.1.2,
        -         myTable.myTableEntry.4.1.2 }

        This will be transform into one call to my_table:

        my_table(get_next, [1, 2], [3, 4])

        The function should now return:

        [{[3, 2, 1], g}, {[5, 1, 1], c}]

        This is illustrated in the following table:

        GetNext from [3,1,2] and [4,1,2].

        The manager now issues the following getNext request:

        getNext{ myTable.myTableEntry,
        -         myTable.myTableEntry.1.3.2 }

        This will be transform into two calls to my_table:

        my_table(get_next, [], [0]) and
        -my_table(get_next, [3, 2], [1])

        The function should now return:

        [{[3, 1, 1], a}] and
        +         myTable.myTableEntry.4.1.2 }

        This will be transform into one call to my_table:

        my_table(get_next, [1, 2], [3, 4])

        The function should now return:

        [{[3, 2, 1], g}, {[5, 1, 1], c}]

        This is illustrated in the following table:

        GetNext from [3,1,2] and [4,1,2].

        The manager now issues the following getNext request:

        getNext{ myTable.myTableEntry,
        +         myTable.myTableEntry.1.3.2 }

        This will be transform into two calls to my_table:

        my_table(get_next, [], [0]) and
        +my_table(get_next, [3, 2], [1])

        The function should now return:

        [{[3, 1, 1], a}] and
         [{[3, 1, 1], a}]

        In both cases, the first accessible element in the table should be returned. As the key columns are not accessible, this means that the third column is the first row.

        Note

        Normally, the functions described above behave exactly as shown, but they are @@ -149,17 +149,17 @@ variables for a device, ipAdr and name with object identifiers 1.1.23.4 and 1.1.7 respectively. To access these variables, one could implement the two Erlang functions ip_access and name_access, which will be in the MIB. The -functions could be specified in a text file as follows:

        {ipAdr, {my_module, ip_access, []}}.
        +functions could be specified in a text file as follows:

        {ipAdr, {my_module, ip_access, []}}.
         % Or using the oid syntax for 'name'
        -{[1,1,7], {my_module, name_access, []}}.

        The ExtraArgument parameter is the empty list. For example, when the agent +{[1,1,7], {my_module, name_access, []}}.

        The ExtraArgument parameter is the empty list. For example, when the agent receives a get-request for the ipAdr variable, a call will be made to ip_access(get). The value returned by this function is the answer to the get-request.

        If ip_access and name_access are implemented similarly, we could write a -generic_access function using the ListOfExtraArguments:

        {ipAdr, {my_module, generic_access, ['IPADR']}}.
        +generic_access function using the ListOfExtraArguments:

        {ipAdr, {my_module, generic_access, ['IPADR']}}.
         % The mnemonic 'name' is more convenient than 1.1.7
        -{name, {my_module, generic_access, ['NAME']}}.

        When the agent receives the same get-request as above, a call will be made to -generic_access(get,'IPADR').

        Yet another possibility, closer to the hardware, could be:

        {ipAdr, {my_module, generic_access, [16#2543]}}.
        -{name, {my_module, generic_access, [16#A2B3]}}.

        Default Instrumentation

        When the MIB definition work is finished, there are two major issues left.

        • Implementing the MIB
        • Implementing a Manager Application.

        Implementing an MIB can be a tedious task. Most probably, there is a need to +{name, {my_module, generic_access, ['NAME']}}.

        When the agent receives the same get-request as above, a call will be made to +generic_access(get,'IPADR').

        Yet another possibility, closer to the hardware, could be:

        {ipAdr, {my_module, generic_access, [16#2543]}}.
        +{name, {my_module, generic_access, [16#A2B3]}}.

        Default Instrumentation

        When the MIB definition work is finished, there are two major issues left.

        • Implementing the MIB
        • Implementing a Manager Application.

        Implementing an MIB can be a tedious task. Most probably, there is a need to test the agent before all tables and variables are implemented. In this case, the default instrumentation functions are useful. The toolkit can generate default instrumentation functions for variables as well as for tables. /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_manager_config_files.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1067)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_manager_config_files.html 2026-08-21 04:00:27.739348895 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_manager_config_files.html 2026-08-21 04:00:27.740348901 +0000 @@ -107,32 +107,32 @@ every transport.

      • engine_id - The SnmpEngineID as defined in SNMP-FRAMEWORK-MIB. Mandatory.

      • max_message_size - The snmpEngineMaxMessageSize as defined in SNMP-FRAMEWORK-MIB. Mandatory.

    • Value is the value for the variable.

    The legacy and intermediate variables address and domain are still supported -so old configurations will work.

    The following example shows a manager.conf file:

    {transports,       [{transportDomainUdpIpv4, {{141,213,11,24}, 5000}},
    -                    {transportDomainUdpIpv6, {{0,0,0,0,0,0,0,1}, 5000}}]}.
    -{engine_id,        "mgrEngine"}.
    -{max_message_size, 484}.

    The value of engine_id is a string, which should have a very specific +so old configurations will work.

    The following example shows a manager.conf file:

    {transports,       [{transportDomainUdpIpv4, {{141,213,11,24}, 5000}},
    +                    {transportDomainUdpIpv6, {{0,0,0,0,0,0,0,1}, 5000}}]}.
    +{engine_id,        "mgrEngine"}.
    +{max_message_size, 484}.

    The value of engine_id is a string, which should have a very specific structure. See RFC 2271/2571 for details.

    And this is a code (snippet) example of how to generate this file in runtime:

    ManagerDir    = "/tmp",
     Port          = 5000,
    -Addr4         = {141,213,11,24},
    -Addr6         = {0,0,0,0,0,0,0,1},
    -Transports    = [{transportDomainUdpIpv4, {Addr4, Port}},
    -                 {transportDomainUdpIpv6, {Addr6, Port}}],
    +Addr4         = {141,213,11,24},
    +Addr6         = {0,0,0,0,0,0,0,1},
    +Transports    = [{transportDomainUdpIpv4, {Addr4, Port}},
    +                 {transportDomainUdpIpv6, {Addr6, Port}}],
     EngineID      = "mgrEngine",
     MMS           = 484,
    -ManagerConfig = [snmpm_conf:manager_entry(transports,       Transports),
    -                 snmpm_conf:manager_entry(engine_id,        EngineID),
    -                 snmpm_conf:manager_entry(max_message_size, MMS)],
    -snmpm_conf:write_manager_config(ManagerDir, ManagerConfig),

    Users

    For each manager user, the manager needs some information. This information is +ManagerConfig = [snmpm_conf:manager_entry(transports, Transports), + snmpm_conf:manager_entry(engine_id, EngineID), + snmpm_conf:manager_entry(max_message_size, MMS)], +snmpm_conf:write_manager_config(ManagerDir, ManagerConfig),

    Users

    For each manager user, the manager needs some information. This information is either added in the users.conf config file or by calling the register_user function in run-time.

    Each row defines a manager user of the manager.

    Each entry is a tuple of size four:

    {UserId, UserMod, UserData, DefaultAgentConfig}.

    • UserId is any term (used to uniquely identify the user).
    • UserMod is the user callback module (atom).
    • UserData is any term (passed on to the user when calling the UserMod.
    • DefaultAgentConfig is a list of default agent config's. These values are used as default values when this user registers agents.

    And this is a code (snippet) example of how to generate this file in runtime:

    ManagerDir         = "/tmp",
    -UserID             = make_ref(),
    +UserID             = make_ref(),
     UserMod            = my_manager_callback_mod,
    -UserData           = self(),
    -DefaultAgentConfig = [{version, v1}, {timeout, 2500}, {max_message_size, 484}],
    -UsersConfig = [snmpm_conf:users_entry(UserID, UserMod, UserData,
    -                                      DefaultAgentConfig)],
    -snmpm_conf:write_users_config(ManagerDir, UsersConfig),

    Agents

    The information needed to handle agents should be stored in a file called +UserData = self(), +DefaultAgentConfig = [{version, v1}, {timeout, 2500}, {max_message_size, 484}], +UsersConfig = [snmpm_conf:users_entry(UserID, UserMod, UserData, + DefaultAgentConfig)], +snmpm_conf:write_users_config(ManagerDir, UsersConfig),

    Agents

    The information needed to handle agents should be stored in a file called agents.conf. It is also possible to add agents in run-time by calling the register_agent.

    Each entry is a tuple:

    {UserId, TargetName, Comm, Domain, Addr, EngineID, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel}.

    • UserId is the identity of the manager user responsible for this agent (term).
    • TargetName is a unique non-empty string.
    • Comm is the community string (string).
    • Domain is the transport domain, either transportDomainUdpIpv4 or @@ -144,23 +144,23 @@ (integer).
    • Version is the version (v1 | v2 | v3).

    • SecModel is the security model (any | v1 | v2c | usm).

    • SecName is the security name (string).
    • SecLevel is security level (noAuthNoPriv | authNoPriv | authPriv).

    Legacy configurations using tuples without Domain element, as well as with all TDomain, Ip and Port elements still work.

    And this is a code (snippet) example of how to generate this file in runtime:

    ManagerDir   = "/tmp",
     UserID       = ...
    -AgentsConfig = [snmpm_conf:agents_entry(UserID,
    +AgentsConfig = [snmpm_conf:agents_entry(UserID,
                                             "target 1",
     					"FOOBAR",
    -					transportDomainUdpIpv4, {{1,2,3,4},161},
    +					transportDomainUdpIpv4, {{1,2,3,4},161},
     					"agent Engine 1"
     					1500,
     					484.
    -					v1, v1, "sec name 1", noAuthNoPriv),
    -		snmpm_conf:agents_entry(UserID,
    +					v1, v1, "sec name 1", noAuthNoPriv),
    +		snmpm_conf:agents_entry(UserID,
                                             "target 2",
     					"FOOBAR",
    -					transportDomainUdpIpv4, {{5,6,7,8},161},
    +					transportDomainUdpIpv4, {{5,6,7,8},161},
     					"agent Engine 2"
     					1500,
     					1000.
    -					v1, v1, "sec name 2", noAuthNoPriv)],
    -snmpm_conf:write_agents_config(ManagerDir, UsersConfig),

    Security data for USM

    The information about Security data for USM should be stored in a file called + v1, v1, "sec name 2", noAuthNoPriv)], +snmpm_conf:write_agents_config(ManagerDir, UsersConfig),

    Security data for USM

    The information about Security data for USM should be stored in a file called usm.conf, which must be present if the manager wishes to use SNMPv3 when communicating with agents. It is also possible to add usm data in run-time by calling the register_usm_user.

    The corresponding table is usmUserTable in the SNMP-USER-BASED-SM-MIB @@ -173,13 +173,13 @@ usmAesCfb128Protocol.

  • PrivKey is a list (of integer). This is the User's secret localized encryption key. It is not visible in the MIB. The length of this key needs to be 16 if usmDESPrivProtocol or usmAesCfb128Protocol is used.

  • ManagerDir = "/tmp",
    -UsmConfig  = [snmpm_conf:usm_entry("engine",
    +UsmConfig  = [snmpm_conf:usm_entry("engine",
                                        "user 1",
     	                           usmNoAuthProtocol,
    -	 			   [],
    +	 			   [],
     	 			   usmNoPrivProtocol,
    -	 			   [])],
    -snmpm_conf:write_usm_config(ManagerDir, UsmConfig),
    + [])], +snmpm_conf:write_usm_config(ManagerDir, UsmConfig), /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_mib_compiler.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1332)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_mib_compiler.html 2026-08-21 04:00:27.759349025 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_mib_compiler.html 2026-08-21 04:00:27.759349025 +0000 @@ -99,16 +99,16 @@ association file, it gives a warning message and uses default instrumentation functions. (See Default Instrumentation for more details).

    The MIB compiler is started with a call to snmpc:compile(<mibname>). For -example:

    snmpc:compile("RFC1213-MIB").

    The output is a new file which is called <mibname>.bin.

    The MIB compiler understands both SMIv1 and SMIv2 MIBs. It uses the +example:

    snmpc:compile("RFC1213-MIB").

    The output is a new file which is called <mibname>.bin.

    The MIB compiler understands both SMIv1 and SMIv2 MIBs. It uses the MODULE-IDENTITY statement to determinate if the MIB is written in SMI version 1 or 2.

    Importing MIBs

    The compiler handles the IMPORT statement. It is important to import the compiled file and not the ASN.1 (source) file. A MIB must be recompiled to make changes visible to other MIBs importing it.

    The compiled files of the imported MIBs must be present in the current directory, or a directory in the current path. The path is supplied with the -{i, Path} option, for example:

    snmpc:compile("MY-MIB",
    -       [{i, ["friend_mibs/", "../standard_mibs/"]}]).

    It is also possible to import MIBs from OTP applications in an "include_lib" -like fashion with the il option. Example:

    snmpc:compile("MY-MIB",
    -       [{il, ["snmp/priv/mibs/", "myapp/priv/mibs/"]}]).

    finds the latest version of the snmp and myapp applications in the OTP +{i, Path} option, for example:

    snmpc:compile("MY-MIB",
    +       [{i, ["friend_mibs/", "../standard_mibs/"]}]).

    It is also possible to import MIBs from OTP applications in an "include_lib" +like fashion with the il option. Example:

    snmpc:compile("MY-MIB",
    +       [{il, ["snmp/priv/mibs/", "myapp/priv/mibs/"]}]).

    finds the latest version of the snmp and myapp applications in the OTP system and uses the expanded paths as include paths.

    Note that an SMIv2 MIB can import an SMIv1 MIB and vice versa.

    The following MIBs are built-ins of the Erlang SNMP compiler: SNMPv2-SMI, RFC-1215, RFC-1212, SNMPv2-TC, SNMPv2-CONF, and RFC1155-SMI. They cannot therefore be compiled separately.

    MIB Consistency Checking

    When an MIB is compiled, the compiler detects if several managed objects use the /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_pdus.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_pdus.html 2026-08-21 04:00:27.782349175 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmp_pdus.html 2026-08-21 04:00:27.782349175 +0000 @@ -99,8 +99,8 @@ Erlang record representations and vice versa. The record definitions can be found in the file snmp/include/snmp_types.hrl. If snmpv3 is used, the module that includes snmp_types.hrl must define the constant SNMP_USE_V3 before the -header file is included. Example:

    -define(SNMP_USE_V3, true).
    --include_lib("snmp/include/snmp_types.hrl").

    Encoding and decoding must be done explicitly when writing your own Net if +header file is included. Example:

    -define(SNMP_USE_V3, true).
    +-include_lib("snmp/include/snmp_types.hrl").

    Encoding and decoding must be done explicitly when writing your own Net if process.

    /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpa.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpa.html 2026-08-21 04:00:27.842349565 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpa.html 2026-08-21 04:00:27.847349598 +0000 @@ -3300,8 +3300,8 @@

    Load a single Mib into an agent. The MibName is the name of the Mib, -including the path to where the compiled mib is found. For example:

              Dir = code:priv_dir(my_app) ++ "/mibs/",
    -          snmpa:load_mib(snmp_master_agent, Dir ++ "MY-MIB").
    +including the path to where the compiled mib is found. For example:

              Dir = code:priv_dir(my_app) ++ "/mibs/",
    +          snmpa:load_mib(snmp_master_agent, Dir ++ "MY-MIB").
    @@ -3417,8 +3417,8 @@

    Load Mibs into an agent. If the agent cannot load all MIBs (the default value of the Force argument is false), it will indicate where loading was aborted. The MibName is the name of the Mib, including the path to where the compiled -mib is found. For example,

              Dir = code:priv_dir(my_app) ++ "/mibs/",
    -          snmpa:load_mibs(snmp_master_agent, [Dir ++ "MY-MIB"]).

    If Force = true then the agent will continue attempting to load each mib even +mib is found. For example,

              Dir = code:priv_dir(my_app) ++ "/mibs/",
    +          snmpa:load_mibs(snmp_master_agent, [Dir ++ "MY-MIB"]).

    If Force = true then the agent will continue attempting to load each mib even after failing to load a previous mib. Use with care.

    @@ -4444,8 +4444,8 @@ -

    Accepted type specifications are:

    -spec register_notification_filter(Agent, Id, Mod, Data) -> ok | {error, Reason}.
    --spec register_notification_filter(Id, Mod, Data, Where) -> ok | {error, Reason}.
    +

    Accepted type specifications are:

    -spec register_notification_filter(Agent, Id, Mod, Data) -> ok | {error, Reason}.
    +-spec register_notification_filter(Id, Mod, Data, Where) -> ok | {error, Reason}.
    @@ -4518,8 +4518,8 @@

    Registers a sub-agent under a sub-tree of another agent.

    It is easy to make mistakes when registering sub-agents and this activity should be done carefully. For example, a strange behaviour would result from the -following configuration:

    snmp_agent:register_subagent(MAPid,[1,2,3,4],SA1),
    -snmp_agent:register_subagent(SA1,[1,2,3], SA2).

    SA2 will not get requests starting with object identifier [1,2,3] since +following configuration:

    snmp_agent:register_subagent(MAPid,[1,2,3,4],SA1),
    +snmp_agent:register_subagent(SA1,[1,2,3], SA2).

    SA2 will not get requests starting with object identifier [1,2,3] since SA1 does not.

    @@ -4964,20 +4964,20 @@ Addresses and if there are no targets for which an Inform-Request is sent, Addresses is the empty list [].

    The receiver will first be sent the snmp_targets message, and then for each address in Addresses list, one of the two snmp_notification messages.

  • {Mod, Func, Args} - The info will be delivered via the function call:

    Mod:Func([Msg | Args])

    where Msg has the same content and purpose as the messages descrived above.

  • Address is a management target address and Addresses is a list of management -target addresses. They are defined as followes:

            Addresses  = [address()]
    -        Address    = address()
    -        address()  = v1_address() | v3_address()
    -        v1_address() = {TDomain, TAddress}
    -        v3_address() = {{TDomain, TAddress}, V3MsgData}
    -        TDomain    = tdoamin()
    -        TAddress   = taddress()
    -        tdomain()  = The oid of snmpUDPDomain
    +target addresses. They are defined as followes:

            Addresses  = [address()]
    +        Address    = address()
    +        address()  = v1_address() | v3_address()
    +        v1_address() = {TDomain, TAddress}
    +        v3_address() = {{TDomain, TAddress}, V3MsgData}
    +        TDomain    = tdoamin()
    +        TAddress   = taddress()
    +        tdomain()  = The oid of snmpUDPDomain
                          This is the only supported transport domain.
    -        taddress() = [A1, A2, A3, A4, P1, P3]
    +        taddress() = [A1, A2, A3, A4, P1, P3]
                          The 4 first bytes makes up the IP-address and the last 2,
                          the UDP-port number.
    -        V3MsgData  = v3_msg_data()
    -        v3_msg_data() = term()

    If Receiver is a notification_delivery_info/0 record, then the information + V3MsgData = v3_msg_data() + v3_msg_data() = term()

    If Receiver is a notification_delivery_info/0 record, then the information about the notification delivery will be delivered to the receiver via the callback functions defined by the snmpa_notification_delivery_info_receiver behaviour according to the content of the notification_delivery_info/0 /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpc_cmd.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (992)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpc_cmd.html 2026-08-21 04:00:27.868349734 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpc_cmd.html 2026-08-21 04:00:27.869349741 +0000 @@ -89,7 +89,7 @@ -

    SNMP MIB compiler frontend

    Synopsis

    snmpc [options] file.mib | file.bin

    Description

    The snmpc program provides a way to run the SNMP MIB compiler of the Erlang +

    SNMP MIB compiler frontend

    Synopsis

    snmpc [options] file.mib | file.bin

    Description

    The snmpc program provides a way to run the SNMP MIB compiler of the Erlang system.

    snmpc compiles an SNMP MIB file. See compile/1,2 for more information.

    It can also be used to generate a header file (.hrl) with definitions of Erlang constants for the objects in the MIB. See mib_to_hrl/1.

    Compiler options

    The following options are supported (note that most of these relate to the /usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpm.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1940)) --- old//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpm.html 2026-08-21 04:00:27.914350034 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/snmp-5.20.2.1/doc/html/snmpm.html 2026-08-21 04:00:27.914350034 +0000 @@ -1973,8 +1973,8 @@

    Load a Mib into the manager. The MibName is the name of the Mib, including -the path to where the compiled mib is found. For example,

              Dir = code:priv_dir(my_app) ++ "/mibs/",
    -          snmpm:load_mib(Dir ++ "MY-MIB").
    +the path to where the compiled mib is found. For example,

              Dir = code:priv_dir(my_app) ++ "/mibs/",
    +          snmpm:load_mib(Dir ++ "MY-MIB").
    @@ -3554,8 +3554,8 @@

    Unload a Mib from the manager. The MibName is the name of the Mib, including -the path to where the compiled mib is found. For example,

              Dir = code:priv_dir(my_app) ++ "/mibs/",
    -          snmpm:unload_mib(Dir ++ "MY-MIB").
    +the path to where the compiled mib is found. For example,

              Dir = code:priv_dir(my_app) ++ "/mibs/",
    +          snmpm:unload_mib(Dir ++ "MY-MIB").
    /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/configurations.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1408)) --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/configurations.html 2026-08-21 04:00:27.937350183 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/configurations.html 2026-08-21 04:00:27.937350183 +0000 @@ -94,23 +94,23 @@ describe and define different ways by which they could be entered.

    Options for hardening are described in the Hardening SSH chapter. How the options for algorithm configuration interact are described in the Configuring algorithms in SSH chapter.

    Options configuration

    There are from OTP-23.0 two main ways to set an option:

    • Like before, in the Options parameter in the Erlang code in a call to for -example ssh:daemon/3 or ssh:connect/3 or any of their variants. Example:

      ssh:connect(22, [{user,"foo"}])
    • In OTP Configuration Parameters:

      • In the erl command line:

        erl -ssh user \"foo\"
      • In the ssh.app file, in the env part

        {application, ssh,
        - [{description, "SSH-2 for Erlang/OTP"},
        -  {vsn, "4.9"},
        -  {modules, [ssh,
        +example ssh:daemon/3 or ssh:connect/3 or any of their variants. Example:

        ssh:connect(22, [{user,"foo"}])
      • In OTP Configuration Parameters:

        • In the erl command line:

          erl -ssh user \"foo\"
        • In the ssh.app file, in the env part

          {application, ssh,
          + [{description, "SSH-2 for Erlang/OTP"},
          +  {vsn, "4.9"},
          +  {modules, [ssh,
                   ...
          -         ssh_xfer]},
          -  {registered, []},
          -  {applications, [kernel, stdlib, crypto, public_key]},
          -  {env, [{user, "bar"]}, % <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE
          -  {mod, {ssh_app, []}},
          -       ...
        • In a .config file:

          erl -config ex1

          where ex1.config contains:

          [
          -{ssh, [{user, "foo"}]}
          -].

        If the option is intended only for a server or for a client, it may be set in -this way:

        [
        -{ssh, [{server_options,[{user, "foo"}]},
        -       {client_options,[{user, "bar"}]}
        -].

        A server (daemon) will use the user name foo, and a client will use the name + ssh_xfer]}, + {registered, []}, + {applications, [kernel, stdlib, crypto, public_key]}, + {env, [{user, "bar"]}, % <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE + {mod, {ssh_app, []}}, + ...

      • In a .config file:

        erl -config ex1

        where ex1.config contains:

        [
        +{ssh, [{user, "foo"}]}
        +].

      If the option is intended only for a server or for a client, it may be set in +this way:

      [
      +{ssh, [{server_options,[{user, "foo"}]},
      +       {client_options,[{user, "bar"}]}
      +].

      A server (daemon) will use the user name foo, and a client will use the name bar.

    Precedence

    If an option is set in more than one way, what happens?

    There is an ordering, which is:

    If the same option is set at two different levels, the one at the highest level is used.

    The only exception is the @@ -169,17 +169,17 @@ 'hmac-sha1']}]}, {compression,[{client2server,[none,'zlib@openssh.com']}, {server2client,[none,'zlib@openssh.com']}]}]

    Note that the algorithms in the file ex2.config is not yet applied. They will -be when we start ssh:

    2> ssh:start().
    +be when we start ssh:

    2> ssh:start().
     ok
    -3> ssh:default_algorithms().
    -[{kex,['ecdh-sha2-nistp384']},
    - {public_key,['ssh-rsa']},
    - {cipher,[{client2server,['aes192-ctr']},
    -          {server2client,['aes192-ctr']}]},
    - {mac,[{client2server,['hmac-sha1']},
    -       {server2client,['hmac-sha1']}]},
    - {compression,[{client2server,[none,'zlib@openssh.com']},
    -               {server2client,[none,'zlib@openssh.com']}]}]
    +3> ssh:default_algorithms().
    +[{kex,['ecdh-sha2-nistp384']},
    + {public_key,['ssh-rsa']},
    + {cipher,[{client2server,['aes192-ctr']},
    +          {server2client,['aes192-ctr']}]},
    + {mac,[{client2server,['hmac-sha1']},
    +       {server2client,['hmac-sha1']}]},
    + {compression,[{client2server,[none,'zlib@openssh.com']},
    +               {server2client,[none,'zlib@openssh.com']}]}]
     4>

    We see that the algorithm set is changed to the one in the ex2.config. Since compression is not specified in the file, the hard-coded default is still used for that entry.

    Establishing a connection (ssh:connect et al) or starting a daemon (ssh:daemon)

    Both when the client establishes a connection with ssh:connect or other @@ -192,65 +192,65 @@ modify_algorithms on all levels in order starting with level 0 are applied.

    We continue the example above by connecting to a server and modifying the kex algorithm set. We remove the only one ('ecdh-sha2-nistp384') and add -'curve25519-sha256@libssh.org' by appending it to the now empty list:

    4> {ok,C} = ssh:connect(loopback, 22,
    -                        [{modify_algorithms,
    -                                 [{rm,
    -                                     [ {kex,['ecdh-sha2-nistp384']} ]
    -				  },
    -                                  {append,
    -			             [ {kex,['curve25519-sha256@libssh.org']} ]
    -				  }
    -				 ]
    -	                 }
    -                        ]).
    -{ok,>0.118.0>}

    We check which algorithms are negotiated by the client and the server, and note -that the (only) kex algorithm 'curve25519-sha256@libssh.org' was selected:

    5> ssh:connection_info(C, algorithms).
    -{algorithms,[{kex,'curve25519-sha256@libssh.org'},
    -             {hkey,'ssh-rsa'},
    -             {send_mac,'hmac-sha1'},
    -             {recv_mac,'hmac-sha1'},
    -             {encrypt,'aes192-ctr'},
    -             {decrypt,'aes192-ctr'},
    -             {compress,none},
    -             {decompress,none},
    -             {send_ext_info,false},
    -             {recv_ext_info,true}]}

    Example of modify_algorithms handling

    We will now check if the +'curve25519-sha256@libssh.org' by appending it to the now empty list:

    4> {ok,C} = ssh:connect(loopback, 22,
    +                        [{modify_algorithms,
    +                                 [{rm,
    +                                     [ {kex,['ecdh-sha2-nistp384']} ]
    +				  },
    +                                  {append,
    +			             [ {kex,['curve25519-sha256@libssh.org']} ]
    +				  }
    +				 ]
    +	                 }
    +                        ]).
    +{ok,>0.118.0>}

    We check which algorithms are negotiated by the client and the server, and note +that the (only) kex algorithm 'curve25519-sha256@libssh.org' was selected:

    5> ssh:connection_info(C, algorithms).
    +{algorithms,[{kex,'curve25519-sha256@libssh.org'},
    +             {hkey,'ssh-rsa'},
    +             {send_mac,'hmac-sha1'},
    +             {recv_mac,'hmac-sha1'},
    +             {encrypt,'aes192-ctr'},
    +             {decrypt,'aes192-ctr'},
    +             {compress,none},
    +             {decompress,none},
    +             {send_ext_info,false},
    +             {recv_ext_info,true}]}

    Example of modify_algorithms handling

    We will now check if the modify_algorithms on a lower level is applied to a preferred_algorithms on a higher level. We will do that by enabling the ssh-dss algorithm that is supported, -but not in the default set.

    The config file ex3.config has the contents:

    [
    - {ssh, [{modify_algorithms,
    -         [ {prepend, [{public_key, ['ssh-dss']}]} ]
    -        }]}
    -].

    A newly started erlang shell shows that no 'ssh-dss' is present in the -public_key entry:

    1> proplists:get_value(public_key, ssh:default_algorithms()).
    -['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
    +but not in the default set.

    The config file ex3.config has the contents:

    [
    + {ssh, [{modify_algorithms,
    +         [ {prepend, [{public_key, ['ssh-dss']}]} ]
    +        }]}
    +].

    A newly started erlang shell shows that no 'ssh-dss' is present in the +public_key entry:

    1> proplists:get_value(public_key, ssh:default_algorithms()).
    +['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
      'ecdsa-sha2-nistp256','ssh-ed25519','ssh-ed448',
    - 'rsa-sha2-256','rsa-sha2-512','ssh-rsa']
    -2>

    A call to ssh:connect/3 removes all algorithms but one of each type:

    2> ssh:start().
    + 'rsa-sha2-256','rsa-sha2-512','ssh-rsa']
    +2>

    A call to ssh:connect/3 removes all algorithms but one of each type:

    2> ssh:start().
     ok
    -3> {ok,C} = ssh:connect(loopback, 22,
    -                        [{preferred_algorithms,
    -                         [{public_key, ['ecdsa-sha2-nistp256']},
    -			  {kex, ['ecdh-sha2-nistp256']},
    -		          {cipher, ['chacha20-poly1305@openssh.com']},
    -			  {mac, ['hmac-sha2-256']},
    -			  {compression, [none]}
    -			  ]}
    -			 ]).
    -{ok,<0.101.0>}
    -4> ssh:connection_info(C,algorithms).
    -{algorithms,[{kex,'ecdh-sha2-nistp256'},
    -             {hkey,'ssh-dss'},
    -             {send_mac,'chacha20-poly1305@openssh.com'},
    -             {recv_mac,'chacha20-poly1305@openssh.com'},
    -             {encrypt,'chacha20-poly1305@openssh.com'},
    -             {decrypt,'chacha20-poly1305@openssh.com'},
    -             {compress,none},
    -             {decompress,none},
    -             {send_ext_info,false},
    -             {recv_ext_info,true}]}
    +3> {ok,C} = ssh:connect(loopback, 22,
    +                        [{preferred_algorithms,
    +                         [{public_key, ['ecdsa-sha2-nistp256']},
    +			  {kex, ['ecdh-sha2-nistp256']},
    +		          {cipher, ['chacha20-poly1305@openssh.com']},
    +			  {mac, ['hmac-sha2-256']},
    +			  {compression, [none]}
    +			  ]}
    +			 ]).
    +{ok,<0.101.0>}
    +4> ssh:connection_info(C,algorithms).
    +{algorithms,[{kex,'ecdh-sha2-nistp256'},
    +             {hkey,'ssh-dss'},
    +             {send_mac,'chacha20-poly1305@openssh.com'},
    +             {recv_mac,'chacha20-poly1305@openssh.com'},
    +             {encrypt,'chacha20-poly1305@openssh.com'},
    +             {decrypt,'chacha20-poly1305@openssh.com'},
    +             {compress,none},
    +             {decompress,none},
    +             {send_ext_info,false},
    +             {recv_ext_info,true}]}
     5>

    But 'ssh-dss' is selected although the call inserted only 'ecdsa-sha2-nistp256' as acceptable.

    This example showed that we could augment the set of algorithms with a config-file without the need to change the actual call.

    For demonstration purposes we used prepend instead of append. This forces /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/configure_algos.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1058)) --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/configure_algos.html 2026-08-21 04:00:27.963350353 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/configure_algos.html 2026-08-21 04:00:27.965350366 +0000 @@ -118,29 +118,29 @@ supported by the:

    • crypto app,
    • The cryptolib OTP is linked with, usually the one the OS uses, probably OpenSSL,
    • and finally what the SSH app implements

    Due to this, it impossible to list in documentation what algorithms that are available in a certain installation.

    There is an important command to list the actual algorithms and their ordering: -ssh:default_algorithms/0.

    0> ssh:default_algorithms().
    -[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
    +ssh:default_algorithms/0.

    0> ssh:default_algorithms().
    +[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
            'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256',
            'diffie-hellman-group16-sha512',
            'diffie-hellman-group18-sha512',
            'diffie-hellman-group14-sha256',
            'diffie-hellman-group14-sha1',
    -       'diffie-hellman-group-exchange-sha1']},
    - {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
    +       'diffie-hellman-group-exchange-sha1']},
    + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
                   'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
    -              'rsa-sha2-512','ssh-dss']},
    - {cipher,[{client2server,['aes256-gcm@openssh.com',
    +              'rsa-sha2-512','ssh-dss']},
    + {cipher,[{client2server,['aes256-gcm@openssh.com',
                               'aes256-ctr','aes192-ctr','aes128-gcm@openssh.com',
    -                          'aes128-ctr','aes128-cbc','3des-cbc']},
    -          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
    +                          'aes128-ctr','aes128-cbc','3des-cbc']},
    +          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
                               'aes192-ctr','aes128-gcm@openssh.com','aes128-ctr',
    -                          'aes128-cbc','3des-cbc']}]},
    - {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']},
    -       {server2client,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']}]},
    - {compression,[{client2server,[none,'zlib@openssh.com']},
    -               {server2client,[none,'zlib@openssh.com']}]}]

    To change the algorithm list, there are two options which can be used in + 'aes128-cbc','3des-cbc']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com']}, + {server2client,[none,'zlib@openssh.com']}]}]

    To change the algorithm list, there are two options which can be used in ssh:connect/2,3,4 and ssh:daemon/2,3. The options could of course be used in all other functions that initiates connections.

    The options are @@ -151,98 +151,98 @@ ssh:chk_algos_opts(Opts). It mangles the options preferred_algorithms and modify_algorithms in the same way as ssh:daemon, ssh:connect and their friends does.

    Example 1

    Replace the kex algorithms list with the single algorithm -'diffie-hellman-group14-sha256':

    1> ssh:chk_algos_opts(
    -               [{preferred_algorithms,
    -                     [{kex, ['diffie-hellman-group14-sha256']}
    -                     ]
    -                }
    -              ]).
    -[{kex,['diffie-hellman-group14-sha256']},
    - {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
    +'diffie-hellman-group14-sha256':

    1> ssh:chk_algos_opts(
    +               [{preferred_algorithms,
    +                     [{kex, ['diffie-hellman-group14-sha256']}
    +                     ]
    +                }
    +              ]).
    +[{kex,['diffie-hellman-group14-sha256']},
    + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
                   'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
    -              'rsa-sha2-512','ssh-dss']},
    - {cipher,[{client2server,['aes256-gcm@openssh.com',
    +              'rsa-sha2-512','ssh-dss']},
    + {cipher,[{client2server,['aes256-gcm@openssh.com',
                               'aes256-ctr','aes192-ctr','aes128-gcm@openssh.com',
    -                          'aes128-ctr','aes128-cbc','3des-cbc']},
    -          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
    +                          'aes128-ctr','aes128-cbc','3des-cbc']},
    +          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
                               'aes192-ctr','aes128-gcm@openssh.com','aes128-ctr',
    -                          'aes128-cbc','3des-cbc']}]},
    - {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']},
    -       {server2client,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']}]},
    - {compression,[{client2server,[none,'zlib@openssh.com']},
    -               {server2client,[none,'zlib@openssh.com']}]}]

    Note that the unmentioned lists (public_key, cipher, mac and + 'aes128-cbc','3des-cbc']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com']}, + {server2client,[none,'zlib@openssh.com']}]}]

    Note that the unmentioned lists (public_key, cipher, mac and compression) are unchanged.

    Example 2

    In the lists that are divided in two for the two directions (for example cipher) it is -possible to change both directions at once:

    2> ssh:chk_algos_opts(
    -               [{preferred_algorithms,
    -                     [{cipher,['aes128-ctr']}
    -                     ]
    -                }
    -              ]).
    -[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
    +possible to change both directions at once:

    2> ssh:chk_algos_opts(
    +               [{preferred_algorithms,
    +                     [{cipher,['aes128-ctr']}
    +                     ]
    +                }
    +              ]).
    +[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
            'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256',
            'diffie-hellman-group16-sha512',
            'diffie-hellman-group18-sha512',
            'diffie-hellman-group14-sha256',
            'diffie-hellman-group14-sha1',
    -       'diffie-hellman-group-exchange-sha1']},
    - {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
    +       'diffie-hellman-group-exchange-sha1']},
    + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
                   'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
    -              'rsa-sha2-512','ssh-dss']},
    - {cipher,[{client2server,['aes128-ctr']},
    -          {server2client,['aes128-ctr']}]},
    - {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']},
    -       {server2client,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']}]},
    - {compression,[{client2server,[none,'zlib@openssh.com']},
    -               {server2client,[none,'zlib@openssh.com']}]}]

    Note that both lists in cipher has been changed to the provided value + 'rsa-sha2-512','ssh-dss']}, + {cipher,[{client2server,['aes128-ctr']}, + {server2client,['aes128-ctr']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com']}, + {server2client,[none,'zlib@openssh.com']}]}]

    Note that both lists in cipher has been changed to the provided value ('aes128-ctr').

    Example 3

    In the lists that are divided in two for the two directions (for example cipher) it is -possible to change only one of the directions:

    3> ssh:chk_algos_opts(
    -               [{preferred_algorithms,
    -                     [{cipher,[{client2server,['aes128-ctr']}]}
    -                     ]
    -                }
    -              ]).
    -[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
    +possible to change only one of the directions:

    3> ssh:chk_algos_opts(
    +               [{preferred_algorithms,
    +                     [{cipher,[{client2server,['aes128-ctr']}]}
    +                     ]
    +                }
    +              ]).
    +[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
            'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256',
            'diffie-hellman-group16-sha512',
            'diffie-hellman-group18-sha512',
            'diffie-hellman-group14-sha256',
            'diffie-hellman-group14-sha1',
    -       'diffie-hellman-group-exchange-sha1']},
    - {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
    +       'diffie-hellman-group-exchange-sha1']},
    + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
                   'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
    -              'rsa-sha2-512','ssh-dss']},
    - {cipher,[{client2server,['aes128-ctr']},
    -          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
    +              'rsa-sha2-512','ssh-dss']},
    + {cipher,[{client2server,['aes128-ctr']},
    +          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
                               'aes192-ctr','aes128-gcm@openssh.com','aes128-ctr',
    -                          'aes128-cbc','3des-cbc']}]},
    - {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']},
    -       {server2client,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']}]},
    - {compression,[{client2server,[none,'zlib@openssh.com']},
    -               {server2client,[none,'zlib@openssh.com']}]}]

    Example 4

    It is of course possible to change more than one list:

    4> ssh:chk_algos_opts(
    -               [{preferred_algorithms,
    -                     [{cipher,['aes128-ctr']},
    -		      {mac,['hmac-sha2-256']},
    -                      {kex,['ecdh-sha2-nistp384']},
    -		      {public_key,['ssh-rsa']},
    -		      {compression,[{server2client,[none]},
    -		                    {client2server,[zlib]}]}
    -                     ]
    -                }
    -              ]).
    -[{kex,['ecdh-sha2-nistp384']},
    - {public_key,['ssh-rsa']},
    - {cipher,[{client2server,['aes128-ctr']},
    -          {server2client,['aes128-ctr']}]},
    - {mac,[{client2server,['hmac-sha2-256']},
    -       {server2client,['hmac-sha2-256']}]},
    - {compression,[{client2server,[zlib]},
    -               {server2client,[none]}]}]

    Note that the order of the tuples in the lists does not matter.

    Modifying the default set: modify_algorithms

    A situation where it might be useful to add an algorithm is when one need to use + 'aes128-cbc','3des-cbc']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com']}, + {server2client,[none,'zlib@openssh.com']}]}]

    Example 4

    It is of course possible to change more than one list:

    4> ssh:chk_algos_opts(
    +               [{preferred_algorithms,
    /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/hardening.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1013))
    --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/hardening.html	2026-08-21 04:00:27.986350502 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/hardening.html	2026-08-21 04:00:27.987350509 +0000
    @@ -150,16 +150,16 @@
     could be replaced with a pwdfun plugin. The arity
     four variant (pwdfun_4()) can also be used for
     introducing delays after failed password checking attempts. Here is a simple
    -example of such a pwdfun:

    fun(User, Password, _PeerAddress, State) ->
    -        case lists:member({User,Password}, my_user_pwds()) of
    +example of such a pwdfun:

    fun(User, Password, _PeerAddress, State) ->
    +        case lists:member({User,Password}, my_user_pwds()) of
                 true ->
    -                {true, undefined}; % Reset delay time
    +                {true, undefined}; % Reset delay time
                 false when State == undefined ->
    -                timer:sleep(1000),
    -                {false, 2000}; % Next delay is 2000 ms
    -            false when is_integer(State) ->
    -                timer:sleep(State),
    -                {false, 2*State} % Double the delay for each failure
    +                timer:sleep(1000),
    +                {false, 2000}; % Next delay is 2000 ms
    +            false when is_integer(State) ->
    +                timer:sleep(State),
    +                {false, 2*State} % Double the delay for each failure
             end
     end.

    If a public key is used for logging in, there is normally no checking of the user name. It could be enabled by setting the option @@ -192,7 +192,7 @@ exploiting known faults or peculiarities learned by reading the public code.

    Each SSH client or daemon presents themselves to each other with brand and version. This may look like

    SSH-2.0-Erlang/4.10

    or

    SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3

    This brand and version may be changed with the option id_string. We start a daemon with that -option:

    	ssh:daemon(1234, [{id_string,"hi there"}, ... ]).

    and the daemon will present itself as:

    SSH-2.0-hi there

    It is possible to replace the string with one randomly generated for each +option:

    	ssh:daemon(1234, [{id_string,"hi there"}, ... ]).

    and the daemon will present itself as:

    SSH-2.0-hi there

    It is possible to replace the string with one randomly generated for each connection attempt. See the reference manual for id_string.

    Symbolic links inside the SFTP root that point outside it can be followed by file operations such as open, read, and stat. The root option @@ -212,10 +212,10 @@ is in milliseconds, and the initial value is infinity.

    The negotiation (session setup time) time can be limited with the parameter NegotiationTimeout in a call establishing an ssh session, for example ssh:connect/3.

    SFTP Security

    Root Directory Isolation

    The root option (see ssh_sftpd) restricts SFTP users to a -specific directory tree, preventing access to files outside that directory.

    Example:

    ssh:daemon(Port, [
    -    {subsystems, [ssh_sftpd:subsystem_spec([{root, "/home/sftpuser"}])]},
    +specific directory tree, preventing access to files outside that directory.

    Example:

    ssh:daemon(Port, [
    +    {subsystems, [ssh_sftpd:subsystem_spec([{root, "/home/sftpuser"}])]},
         ...
    -]).

    Important: The root option is configured per daemon, not per user. All +]).

    Important: The root option is configured per daemon, not per user. All users connecting to the same daemon share the same root directory. For per-user isolation, consider running separate daemon instances on different ports or using OS-level mechanisms (PAM chroot, containers, file permissions).

    Defense-in-depth: For high-security deployments, combine the root option /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/configurations.xhtml differs (HTML document, ASCII text, with very long lines (1397)) --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/configurations.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/configurations.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -22,23 +22,23 @@ describe and define different ways by which they could be entered.

    Options for hardening are described in the Hardening SSH chapter. How the options for algorithm configuration interact are described in the Configuring algorithms in SSH chapter.

    Options configuration

    There are from OTP-23.0 two main ways to set an option:

    • Like before, in the Options parameter in the Erlang code in a call to for -example ssh:daemon/3 or ssh:connect/3 or any of their variants. Example:

      ssh:connect(22, [{user,"foo"}])
    • In OTP Configuration Parameters:

      • In the erl command line:

        erl -ssh user \"foo\"
      • In the ssh.app file, in the env part

        {application, ssh,
        - [{description, "SSH-2 for Erlang/OTP"},
        -  {vsn, "4.9"},
        -  {modules, [ssh,
        +example ssh:daemon/3 or ssh:connect/3 or any of their variants. Example:

        ssh:connect(22, [{user,"foo"}])
      • In OTP Configuration Parameters:

        • In the erl command line:

          erl -ssh user \"foo\"
        • In the ssh.app file, in the env part

          {application, ssh,
          + [{description, "SSH-2 for Erlang/OTP"},
          +  {vsn, "4.9"},
          +  {modules, [ssh,
                   ...
          -         ssh_xfer]},
          -  {registered, []},
          -  {applications, [kernel, stdlib, crypto, public_key]},
          -  {env, [{user, "bar"]}, % <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE
          -  {mod, {ssh_app, []}},
          -       ...
        • In a .config file:

          erl -config ex1

          where ex1.config contains:

          [
          -{ssh, [{user, "foo"}]}
          -].

        If the option is intended only for a server or for a client, it may be set in -this way:

        [
        -{ssh, [{server_options,[{user, "foo"}]},
        -       {client_options,[{user, "bar"}]}
        -].

        A server (daemon) will use the user name foo, and a client will use the name + ssh_xfer]}, + {registered, []}, + {applications, [kernel, stdlib, crypto, public_key]}, + {env, [{user, "bar"]}, % <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE + {mod, {ssh_app, []}}, + ...

  • In a .config file:

    erl -config ex1

    where ex1.config contains:

    [
    +{ssh, [{user, "foo"}]}
    +].
  • If the option is intended only for a server or for a client, it may be set in +this way:

    [
    +{ssh, [{server_options,[{user, "foo"}]},
    +       {client_options,[{user, "bar"}]}
    +].

    A server (daemon) will use the user name foo, and a client will use the name bar.

    Precedence

    If an option is set in more than one way, what happens?

    There is an ordering, which is:

    If the same option is set at two different levels, the one at the highest level is used.

    The only exception is the @@ -97,17 +97,17 @@ 'hmac-sha1']}]}, {compression,[{client2server,[none,'zlib@openssh.com']}, {server2client,[none,'zlib@openssh.com']}]}]

    Note that the algorithms in the file ex2.config is not yet applied. They will -be when we start ssh:

    2> ssh:start().
    +be when we start ssh:

    2> ssh:start().
     ok
    -3> ssh:default_algorithms().
    -[{kex,['ecdh-sha2-nistp384']},
    - {public_key,['ssh-rsa']},
    - {cipher,[{client2server,['aes192-ctr']},
    -          {server2client,['aes192-ctr']}]},
    - {mac,[{client2server,['hmac-sha1']},
    -       {server2client,['hmac-sha1']}]},
    - {compression,[{client2server,[none,'zlib@openssh.com']},
    -               {server2client,[none,'zlib@openssh.com']}]}]
    +3> ssh:default_algorithms().
    +[{kex,['ecdh-sha2-nistp384']},
    + {public_key,['ssh-rsa']},
    + {cipher,[{client2server,['aes192-ctr']},
    +          {server2client,['aes192-ctr']}]},
    + {mac,[{client2server,['hmac-sha1']},
    +       {server2client,['hmac-sha1']}]},
    + {compression,[{client2server,[none,'zlib@openssh.com']},
    +               {server2client,[none,'zlib@openssh.com']}]}]
     4>

    We see that the algorithm set is changed to the one in the ex2.config. Since compression is not specified in the file, the hard-coded default is still used for that entry.

    Establishing a connection (ssh:connect et al) or starting a daemon (ssh:daemon)

    Both when the client establishes a connection with ssh:connect or other @@ -120,65 +120,65 @@ modify_algorithms on all levels in order starting with level 0 are applied.

    We continue the example above by connecting to a server and modifying the kex algorithm set. We remove the only one ('ecdh-sha2-nistp384') and add -'curve25519-sha256@libssh.org' by appending it to the now empty list:

    4> {ok,C} = ssh:connect(loopback, 22,
    -                        [{modify_algorithms,
    -                                 [{rm,
    -                                     [ {kex,['ecdh-sha2-nistp384']} ]
    -				  },
    -                                  {append,
    -			             [ {kex,['curve25519-sha256@libssh.org']} ]
    -				  }
    -				 ]
    -	                 }
    -                        ]).
    -{ok,>0.118.0>}

    We check which algorithms are negotiated by the client and the server, and note -that the (only) kex algorithm 'curve25519-sha256@libssh.org' was selected:

    5> ssh:connection_info(C, algorithms).
    -{algorithms,[{kex,'curve25519-sha256@libssh.org'},
    -             {hkey,'ssh-rsa'},
    -             {send_mac,'hmac-sha1'},
    -             {recv_mac,'hmac-sha1'},
    -             {encrypt,'aes192-ctr'},
    -             {decrypt,'aes192-ctr'},
    -             {compress,none},
    -             {decompress,none},
    -             {send_ext_info,false},
    -             {recv_ext_info,true}]}

    Example of modify_algorithms handling

    We will now check if the +'curve25519-sha256@libssh.org' by appending it to the now empty list:

    4> {ok,C} = ssh:connect(loopback, 22,
    +                        [{modify_algorithms,
    +                                 [{rm,
    +                                     [ {kex,['ecdh-sha2-nistp384']} ]
    +				  },
    +                                  {append,
    +			             [ {kex,['curve25519-sha256@libssh.org']} ]
    +				  }
    +				 ]
    +	                 }
    +                        ]).
    +{ok,>0.118.0>}

    We check which algorithms are negotiated by the client and the server, and note +that the (only) kex algorithm 'curve25519-sha256@libssh.org' was selected:

    5> ssh:connection_info(C, algorithms).
    +{algorithms,[{kex,'curve25519-sha256@libssh.org'},
    +             {hkey,'ssh-rsa'},
    +             {send_mac,'hmac-sha1'},
    +             {recv_mac,'hmac-sha1'},
    +             {encrypt,'aes192-ctr'},
    +             {decrypt,'aes192-ctr'},
    +             {compress,none},
    +             {decompress,none},
    +             {send_ext_info,false},
    +             {recv_ext_info,true}]}

    Example of modify_algorithms handling

    We will now check if the modify_algorithms on a lower level is applied to a preferred_algorithms on a higher level. We will do that by enabling the ssh-dss algorithm that is supported, -but not in the default set.

    The config file ex3.config has the contents:

    [
    - {ssh, [{modify_algorithms,
    -         [ {prepend, [{public_key, ['ssh-dss']}]} ]
    -        }]}
    -].

    A newly started erlang shell shows that no 'ssh-dss' is present in the -public_key entry:

    1> proplists:get_value(public_key, ssh:default_algorithms()).
    -['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
    +but not in the default set.

    The config file ex3.config has the contents:

    [
    + {ssh, [{modify_algorithms,
    +         [ {prepend, [{public_key, ['ssh-dss']}]} ]
    +        }]}
    +].

    A newly started erlang shell shows that no 'ssh-dss' is present in the +public_key entry:

    1> proplists:get_value(public_key, ssh:default_algorithms()).
    +['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
      'ecdsa-sha2-nistp256','ssh-ed25519','ssh-ed448',
    - 'rsa-sha2-256','rsa-sha2-512','ssh-rsa']
    -2>

    A call to ssh:connect/3 removes all algorithms but one of each type:

    2> ssh:start().
    + 'rsa-sha2-256','rsa-sha2-512','ssh-rsa']
    +2>

    A call to ssh:connect/3 removes all algorithms but one of each type:

    2> ssh:start().
     ok
    -3> {ok,C} = ssh:connect(loopback, 22,
    -                        [{preferred_algorithms,
    -                         [{public_key, ['ecdsa-sha2-nistp256']},
    -			  {kex, ['ecdh-sha2-nistp256']},
    -		          {cipher, ['chacha20-poly1305@openssh.com']},
    -			  {mac, ['hmac-sha2-256']},
    -			  {compression, [none]}
    -			  ]}
    -			 ]).
    -{ok,<0.101.0>}
    -4> ssh:connection_info(C,algorithms).
    -{algorithms,[{kex,'ecdh-sha2-nistp256'},
    -             {hkey,'ssh-dss'},
    -             {send_mac,'chacha20-poly1305@openssh.com'},
    -             {recv_mac,'chacha20-poly1305@openssh.com'},
    -             {encrypt,'chacha20-poly1305@openssh.com'},
    -             {decrypt,'chacha20-poly1305@openssh.com'},
    -             {compress,none},
    -             {decompress,none},
    -             {send_ext_info,false},
    -             {recv_ext_info,true}]}
    +3> {ok,C} = ssh:connect(loopback, 22,
    +                        [{preferred_algorithms,
    +                         [{public_key, ['ecdsa-sha2-nistp256']},
    +			  {kex, ['ecdh-sha2-nistp256']},
    +		          {cipher, ['chacha20-poly1305@openssh.com']},
    +			  {mac, ['hmac-sha2-256']},
    +			  {compression, [none]}
    +			  ]}
    +			 ]).
    +{ok,<0.101.0>}
    +4> ssh:connection_info(C,algorithms).
    +{algorithms,[{kex,'ecdh-sha2-nistp256'},
    +             {hkey,'ssh-dss'},
    +             {send_mac,'chacha20-poly1305@openssh.com'},
    +             {recv_mac,'chacha20-poly1305@openssh.com'},
    +             {encrypt,'chacha20-poly1305@openssh.com'},
    +             {decrypt,'chacha20-poly1305@openssh.com'},
    +             {compress,none},
    +             {decompress,none},
    +             {send_ext_info,false},
    +             {recv_ext_info,true}]}
     5>

    But 'ssh-dss' is selected although the call inserted only 'ecdsa-sha2-nistp256' as acceptable.

    This example showed that we could augment the set of algorithms with a config-file without the need to change the actual call.

    For demonstration purposes we used prepend instead of append. This forces /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/configure_algos.xhtml differs (HTML document, ASCII text, with very long lines (918)) --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/configure_algos.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/configure_algos.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -46,29 +46,29 @@ supported by the:

    • crypto app,
    • The cryptolib OTP is linked with, usually the one the OS uses, probably OpenSSL,
    • and finally what the SSH app implements

    Due to this, it impossible to list in documentation what algorithms that are available in a certain installation.

    There is an important command to list the actual algorithms and their ordering: -ssh:default_algorithms/0.

    0> ssh:default_algorithms().
    -[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
    +ssh:default_algorithms/0.

    0> ssh:default_algorithms().
    +[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
            'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256',
            'diffie-hellman-group16-sha512',
            'diffie-hellman-group18-sha512',
            'diffie-hellman-group14-sha256',
            'diffie-hellman-group14-sha1',
    -       'diffie-hellman-group-exchange-sha1']},
    - {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
    +       'diffie-hellman-group-exchange-sha1']},
    + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
                   'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
    -              'rsa-sha2-512','ssh-dss']},
    - {cipher,[{client2server,['aes256-gcm@openssh.com',
    +              'rsa-sha2-512','ssh-dss']},
    + {cipher,[{client2server,['aes256-gcm@openssh.com',
                               'aes256-ctr','aes192-ctr','aes128-gcm@openssh.com',
    -                          'aes128-ctr','aes128-cbc','3des-cbc']},
    -          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
    +                          'aes128-ctr','aes128-cbc','3des-cbc']},
    +          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
                               'aes192-ctr','aes128-gcm@openssh.com','aes128-ctr',
    -                          'aes128-cbc','3des-cbc']}]},
    - {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']},
    -       {server2client,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']}]},
    - {compression,[{client2server,[none,'zlib@openssh.com']},
    -               {server2client,[none,'zlib@openssh.com']}]}]

    To change the algorithm list, there are two options which can be used in + 'aes128-cbc','3des-cbc']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com']}, + {server2client,[none,'zlib@openssh.com']}]}]

    To change the algorithm list, there are two options which can be used in ssh:connect/2,3,4 and ssh:daemon/2,3. The options could of course be used in all other functions that initiates connections.

    The options are @@ -79,98 +79,98 @@ ssh:chk_algos_opts(Opts). It mangles the options preferred_algorithms and modify_algorithms in the same way as ssh:daemon, ssh:connect and their friends does.

    Example 1

    Replace the kex algorithms list with the single algorithm -'diffie-hellman-group14-sha256':

    1> ssh:chk_algos_opts(
    -               [{preferred_algorithms,
    -                     [{kex, ['diffie-hellman-group14-sha256']}
    -                     ]
    -                }
    -              ]).
    -[{kex,['diffie-hellman-group14-sha256']},
    - {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
    +'diffie-hellman-group14-sha256':

    1> ssh:chk_algos_opts(
    +               [{preferred_algorithms,
    +                     [{kex, ['diffie-hellman-group14-sha256']}
    +                     ]
    +                }
    +              ]).
    +[{kex,['diffie-hellman-group14-sha256']},
    + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
                   'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
    -              'rsa-sha2-512','ssh-dss']},
    - {cipher,[{client2server,['aes256-gcm@openssh.com',
    +              'rsa-sha2-512','ssh-dss']},
    + {cipher,[{client2server,['aes256-gcm@openssh.com',
                               'aes256-ctr','aes192-ctr','aes128-gcm@openssh.com',
    -                          'aes128-ctr','aes128-cbc','3des-cbc']},
    -          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
    +                          'aes128-ctr','aes128-cbc','3des-cbc']},
    +          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
                               'aes192-ctr','aes128-gcm@openssh.com','aes128-ctr',
    -                          'aes128-cbc','3des-cbc']}]},
    - {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']},
    -       {server2client,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']}]},
    - {compression,[{client2server,[none,'zlib@openssh.com']},
    -               {server2client,[none,'zlib@openssh.com']}]}]

    Note that the unmentioned lists (public_key, cipher, mac and + 'aes128-cbc','3des-cbc']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com']}, + {server2client,[none,'zlib@openssh.com']}]}]

    Note that the unmentioned lists (public_key, cipher, mac and compression) are unchanged.

    Example 2

    In the lists that are divided in two for the two directions (for example cipher) it is -possible to change both directions at once:

    2> ssh:chk_algos_opts(
    -               [{preferred_algorithms,
    -                     [{cipher,['aes128-ctr']}
    -                     ]
    -                }
    -              ]).
    -[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
    +possible to change both directions at once:

    2> ssh:chk_algos_opts(
    +               [{preferred_algorithms,
    +                     [{cipher,['aes128-ctr']}
    +                     ]
    +                }
    +              ]).
    +[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
            'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256',
            'diffie-hellman-group16-sha512',
            'diffie-hellman-group18-sha512',
            'diffie-hellman-group14-sha256',
            'diffie-hellman-group14-sha1',
    -       'diffie-hellman-group-exchange-sha1']},
    - {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
    +       'diffie-hellman-group-exchange-sha1']},
    + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
                   'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
    -              'rsa-sha2-512','ssh-dss']},
    - {cipher,[{client2server,['aes128-ctr']},
    -          {server2client,['aes128-ctr']}]},
    - {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']},
    -       {server2client,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']}]},
    - {compression,[{client2server,[none,'zlib@openssh.com']},
    -               {server2client,[none,'zlib@openssh.com']}]}]

    Note that both lists in cipher has been changed to the provided value + 'rsa-sha2-512','ssh-dss']}, + {cipher,[{client2server,['aes128-ctr']}, + {server2client,['aes128-ctr']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com']}, + {server2client,[none,'zlib@openssh.com']}]}]

    Note that both lists in cipher has been changed to the provided value ('aes128-ctr').

    Example 3

    In the lists that are divided in two for the two directions (for example cipher) it is -possible to change only one of the directions:

    3> ssh:chk_algos_opts(
    -               [{preferred_algorithms,
    -                     [{cipher,[{client2server,['aes128-ctr']}]}
    -                     ]
    -                }
    -              ]).
    -[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
    +possible to change only one of the directions:

    3> ssh:chk_algos_opts(
    +               [{preferred_algorithms,
    +                     [{cipher,[{client2server,['aes128-ctr']}]}
    +                     ]
    +                }
    +              ]).
    +[{kex,['ecdh-sha2-nistp384','ecdh-sha2-nistp521',
            'ecdh-sha2-nistp256','diffie-hellman-group-exchange-sha256',
            'diffie-hellman-group16-sha512',
            'diffie-hellman-group18-sha512',
            'diffie-hellman-group14-sha256',
            'diffie-hellman-group14-sha1',
    -       'diffie-hellman-group-exchange-sha1']},
    - {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
    +       'diffie-hellman-group-exchange-sha1']},
    + {public_key,['ecdsa-sha2-nistp384','ecdsa-sha2-nistp521',
                   'ecdsa-sha2-nistp256','ssh-rsa','rsa-sha2-256',
    -              'rsa-sha2-512','ssh-dss']},
    - {cipher,[{client2server,['aes128-ctr']},
    -          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
    +              'rsa-sha2-512','ssh-dss']},
    + {cipher,[{client2server,['aes128-ctr']},
    +          {server2client,['aes256-gcm@openssh.com','aes256-ctr',
                               'aes192-ctr','aes128-gcm@openssh.com','aes128-ctr',
    -                          'aes128-cbc','3des-cbc']}]},
    - {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']},
    -       {server2client,['hmac-sha2-256','hmac-sha2-512',
    -                       'hmac-sha1']}]},
    - {compression,[{client2server,[none,'zlib@openssh.com']},
    -               {server2client,[none,'zlib@openssh.com']}]}]

    Example 4

    It is of course possible to change more than one list:

    4> ssh:chk_algos_opts(
    -               [{preferred_algorithms,
    -                     [{cipher,['aes128-ctr']},
    -		      {mac,['hmac-sha2-256']},
    -                      {kex,['ecdh-sha2-nistp384']},
    -		      {public_key,['ssh-rsa']},
    -		      {compression,[{server2client,[none]},
    -		                    {client2server,[zlib]}]}
    -                     ]
    -                }
    -              ]).
    -[{kex,['ecdh-sha2-nistp384']},
    - {public_key,['ssh-rsa']},
    - {cipher,[{client2server,['aes128-ctr']},
    -          {server2client,['aes128-ctr']}]},
    - {mac,[{client2server,['hmac-sha2-256']},
    -       {server2client,['hmac-sha2-256']}]},
    - {compression,[{client2server,[zlib]},
    -               {server2client,[none]}]}]

    Note that the order of the tuples in the lists does not matter.

    Modifying the default set: modify_algorithms

    A situation where it might be useful to add an algorithm is when one need to use + 'aes128-cbc','3des-cbc']}]}, + {mac,[{client2server,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}, + {server2client,['hmac-sha2-256','hmac-sha2-512', + 'hmac-sha1']}]}, + {compression,[{client2server,[none,'zlib@openssh.com']}, + {server2client,[none,'zlib@openssh.com']}]}]

    Example 4

    It is of course possible to change more than one list:

    4> ssh:chk_algos_opts(
    +               [{preferred_algorithms,
    /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text)
    --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
    @@ -4,10 +4,10 @@
              version="3.0">
       
         ssh - 5.5.2.3
    -    urn:uuid:054615ab-280d-117e-84fc-2d1d00e75b0e
    +    urn:uuid:b88abcb1-5fce-0ce4-1bf8-21f784d7f986
         en
     
    -    2026-08-21T03:49:54Z
    +    2042-09-22T17:08:55Z
     
       
       
    /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/hardening.xhtml differs (HTML document, ASCII text, with very long lines (1013))
    --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/hardening.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/hardening.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -78,16 +78,16 @@
     could be replaced with a pwdfun plugin. The arity
     four variant (pwdfun_4()) can also be used for
     introducing delays after failed password checking attempts. Here is a simple
    -example of such a pwdfun:

    fun(User, Password, _PeerAddress, State) ->
    -        case lists:member({User,Password}, my_user_pwds()) of
    +example of such a pwdfun:

    fun(User, Password, _PeerAddress, State) ->
    +        case lists:member({User,Password}, my_user_pwds()) of
                 true ->
    -                {true, undefined}; % Reset delay time
    +                {true, undefined}; % Reset delay time
                 false when State == undefined ->
    -                timer:sleep(1000),
    -                {false, 2000}; % Next delay is 2000 ms
    -            false when is_integer(State) ->
    -                timer:sleep(State),
    -                {false, 2*State} % Double the delay for each failure
    +                timer:sleep(1000),
    +                {false, 2000}; % Next delay is 2000 ms
    +            false when is_integer(State) ->
    +                timer:sleep(State),
    +                {false, 2*State} % Double the delay for each failure
             end
     end.

    If a public key is used for logging in, there is normally no checking of the user name. It could be enabled by setting the option @@ -120,7 +120,7 @@ exploiting known faults or peculiarities learned by reading the public code.

    Each SSH client or daemon presents themselves to each other with brand and version. This may look like

    SSH-2.0-Erlang/4.10

    or

    SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3

    This brand and version may be changed with the option id_string. We start a daemon with that -option:

    	ssh:daemon(1234, [{id_string,"hi there"}, ... ]).

    and the daemon will present itself as:

    SSH-2.0-hi there

    It is possible to replace the string with one randomly generated for each +option:

    	ssh:daemon(1234, [{id_string,"hi there"}, ... ]).

    and the daemon will present itself as:

    SSH-2.0-hi there

    It is possible to replace the string with one randomly generated for each connection attempt. See the reference manual for id_string.

    Symbolic links inside the SFTP root that point outside it can be followed by file operations such as open, read, and stat. The root option @@ -140,10 +140,10 @@ is in milliseconds, and the initial value is infinity.

    The negotiation (session setup time) time can be limited with the parameter NegotiationTimeout in a call establishing an ssh session, for example ssh:connect/3.

    SFTP Security

    Root Directory Isolation

    The root option (see ssh_sftpd) restricts SFTP users to a -specific directory tree, preventing access to files outside that directory.

    Example:

    ssh:daemon(Port, [
    -    {subsystems, [ssh_sftpd:subsystem_spec([{root, "/home/sftpuser"}])]},
    +specific directory tree, preventing access to files outside that directory.

    Example:

    ssh:daemon(Port, [
    +    {subsystems, [ssh_sftpd:subsystem_spec([{root, "/home/sftpuser"}])]},
         ...
    -]).

    Important: The root option is configured per daemon, not per user. All +]).

    Important: The root option is configured per daemon, not per user. All users connecting to the same daemon share the same root directory. For per-user isolation, consider running separate daemon instances on different ports or using OS-level mechanisms (PAM chroot, containers, file permissions).

    Defense-in-depth: For high-security deployments, combine the root option /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/ssh_agent.xhtml differs (HTML document, ASCII text, with very long lines (983)) --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/ssh_agent.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/ssh_agent.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -29,11 +29,11 @@ authentication.

    Ssh_agent implements the ssh_client_key_api, to allow it to be used by setting the option key_cb when starting a client (with for example ssh:connect, -ssh:shell ).

          {key_cb, {ssh_agent, []}}

    The agent communication is established through a UNIX domain socket. By default, +ssh:shell ).

          {key_cb, {ssh_agent, []}}

    The agent communication is established through a UNIX domain socket. By default, the socket path will be fetched from the SSH_AUTH_SOCK environment variable, which is the default socket path in the agent implementation of OpenSSH.

    In order to set a different socket path the socket_path -option can be set.

          {key_cb, {ssh_agent, [{socket_path, SocketPath}]}}

    Note

    The functions are Callbacks for the SSH app. They are not intended to be +option can be set.

          {key_cb, {ssh_agent, [{socket_path, SocketPath}]}}

    Note

    The functions are Callbacks for the SSH app. They are not intended to be called from the user's code!

    /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/ssh.xhtml differs (HTML document, ASCII text, with very long lines (471)) --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/ssh.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/ssh.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -2179,14 +2179,14 @@

    List of algorithms to use in the algorithm negotiation. The default algs_list/0 can be obtained from default_algorithms/0.

    If an alg_entry() is missing in the algs_list(), the default value is used for -that entry.

    Here is an example of this option:

    	  {preferred_algorithms,
    -	  [{public_key,['ssh-rsa','ssh-dss']},
    -	  {cipher,[{client2server,['aes128-ctr']},
    -          {server2client,['aes128-cbc','3des-cbc']}]},
    -	  {mac,['hmac-sha2-256','hmac-sha1']},
    -	  {compression,[none,zlib]}
    -	  ]
    -	  }

    The example specifies different algorithms in the two directions (client2server +that entry.

    Here is an example of this option:

    	  {preferred_algorithms,
    +	  [{public_key,['ssh-rsa','ssh-dss']},
    +	  {cipher,[{client2server,['aes128-ctr']},
    +          {server2client,['aes128-cbc','3des-cbc']}]},
    +	  {mac,['hmac-sha2-256','hmac-sha1']},
    +	  {compression,[none,zlib]}
    +	  ]
    +	  }

    The example specifies different algorithms in the two directions (client2server and server2client), for cipher but specifies the same algorithms for mac and compression in both directions. The kex (key exchange) is implicit but public_key is set explicitly.

    For background and more examples see the @@ -5404,21 +5404,21 @@

    hostkey_fingerprint([DigestType], HostKey) -> [string()]hostkey_fingerprint(DigestType, HostKey) -> string()

    Calculates a ssh fingerprint from a public host key as openssh does.

    The algorithm in hostkey_fingerprint/1 is md5 to be compatible with older ssh-keygen commands. The string from the second variant is -prepended by the algorithm name in uppercase as in newer ssh-keygen commands.

    Examples:

     2> ssh:hostkey_fingerprint(Key).
    +prepended by the algorithm name in uppercase as in newer ssh-keygen commands.

    Examples:

     2> ssh:hostkey_fingerprint(Key).
      "f5:64:a6:c1:5a:cb:9f:0a:10:46:a2:5c:3e:2f:57:84"
     
    - 3> ssh:hostkey_fingerprint(md5,Key).
    + 3> ssh:hostkey_fingerprint(md5,Key).
      "MD5:f5:64:a6:c1:5a:cb:9f:0a:10:46:a2:5c:3e:2f:57:84"
     
    - 4> ssh:hostkey_fingerprint(sha,Key).
    + 4> ssh:hostkey_fingerprint(sha,Key).
      "SHA1:bSLY/C4QXLDL/Iwmhyg0PGW9UbY"
     
    - 5> ssh:hostkey_fingerprint(sha256,Key).
    + 5> ssh:hostkey_fingerprint(sha256,Key).
      "SHA256:aZGXhabfbf4oxglxltItWeHU7ub3Dc31NcNw2cMJePQ"
     
    - 6> ssh:hostkey_fingerprint([sha,sha256],Key).
    - ["SHA1:bSLY/C4QXLDL/Iwmhyg0PGW9UbY",
    -  "SHA256:aZGXhabfbf4oxglxltItWeHU7ub3Dc31NcNw2cMJePQ"]
    +
    6> ssh:hostkey_fingerprint([sha,sha256],Key). + ["SHA1:bSLY/C4QXLDL/Iwmhyg0PGW9UbY", + "SHA256:aZGXhabfbf4oxglxltItWeHU7ub3Dc31NcNw2cMJePQ"]
    /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/using_ssh.xhtml differs (HTML document, ASCII text, with very long lines (956)) --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/using_ssh.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.epub/OEBPS/using_ssh.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -26,9 +26,9 @@ entering a password). Also, ssh.example.com is a known host in the known_hosts file of the user otptest. This means that host-verification can be done without user-interaction.

    Using the Erlang ssh Terminal Client

    The user otptest, which has bash as default shell, uses the ssh:shell/1 -client to connect to the OpenSSH daemon running on a host called ssh.example.com:

    1> ssh:start().
    +client to connect to the OpenSSH daemon running on a host called ssh.example.com:

    1> ssh:start().
     ok
    -2> {ok, S} = ssh:shell("ssh.example.com").
    +2> {ok, S} = ssh:shell("ssh.example.com").
     otptest@ssh.example.com:> pwd
     /home/otptest
     otptest@ssh.example.com:> exit
    @@ -41,11 +41,11 @@
     [...]
     $bash> ssh-keygen -t rsa -f /tmp/otptest_user/.ssh/id_rsa
     [...]

    Step 2. Create the file /tmp/otptest_user/.ssh/authorized_keys and add the -content of /tmp/otptest_user/.ssh/id_rsa.pub.

    Step 3. Start the Erlang ssh daemon:

    1> ssh:start().
    +content of /tmp/otptest_user/.ssh/id_rsa.pub.

    Step 3. Start the Erlang ssh daemon:

    1> ssh:start().
     ok
    -2> {ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
    -                                  {user_dir, "/tmp/otptest_user/.ssh"}]).
    -{ok,<0.54.0>}
    +2> {ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
    +                                  {user_dir, "/tmp/otptest_user/.ssh"}]).
    +{ok,<0.54.0>}
     3>

    Step 4. Use the OpenSSH client from a shell to connect to the Erlang ssh daemon:

    $bash> ssh ssh.example.com -p 8989  -i /tmp/otptest_user/.ssh/id_rsa \
                       -o UserKnownHostsFile=/tmp/otptest_user/.ssh/known_hosts
    @@ -56,42 +56,42 @@
     Eshell V5.10  (abort with ^G)
     1>

    There are two ways of shutting down an ssh daemon, see Step 5a and Step 5b.

    Step 5a. Shut down the Erlang ssh daemon so that it stops the listener but -leaves existing connections, started by the listener, operational:

    3> ssh:stop_listener(Sshd).
    +leaves existing connections, started by the listener, operational:

    3> ssh:stop_listener(Sshd).
     ok
     4>

    Step 5b. Shut down the Erlang ssh daemon so that it stops the listener and -all connections started by the listener:

    3> ssh:stop_daemon(Sshd).
    +all connections started by the listener:

    3> ssh:stop_daemon(Sshd).
     ok
     4>

    One-Time Execution

    Erlang client contacting OS standard ssh server

    In the following example, the Erlang shell is the client process that receives the channel replies as Erlang messages.

    Do an one-time execution of a remote OS command ("pwd") over ssh to the ssh -server of the OS at the host "ssh.example.com":

    1> ssh:start().
    +server of the OS at the host "ssh.example.com":

    1> ssh:start().
     ok
    -2> {ok, ConnectionRef} = ssh:connect("ssh.example.com", 22, []).
    -{ok,<0.57.0>}
    -3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    -{ok,0}
    -4> success = ssh_connection:exec(ConnectionRef, ChannelId, "pwd", infinity).
    -5> flush(). % Get all pending messages. NOTE: ordering may vary!
    -Shell got {ssh_cm,<0.57.0>,{data,0,0,<<"/home/otptest\n">>}}
    -Shell got {ssh_cm,<0.57.0>,{eof,0}}
    -Shell got {ssh_cm,<0.57.0>,{exit_status,0,0}}
    -Shell got {ssh_cm,<0.57.0>,{closed,0}}
    +2> {ok, ConnectionRef} = ssh:connect("ssh.example.com", 22, []).
    +{ok,<0.57.0>}
    +3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    +{ok,0}
    +4> success = ssh_connection:exec(ConnectionRef, ChannelId, "pwd", infinity).
    +5> flush(). % Get all pending messages. NOTE: ordering may vary!
    +Shell got {ssh_cm,<0.57.0>,{data,0,0,<<"/home/otptest\n">>}}
    +Shell got {ssh_cm,<0.57.0>,{eof,0}}
    +Shell got {ssh_cm,<0.57.0>,{exit_status,0,0}}
    +Shell got {ssh_cm,<0.57.0>,{closed,0}}
     ok
    -6> ssh:connection_info(ConnectionRef, channels).
    -{channels,[]}
    +6> ssh:connection_info(ConnectionRef, channels).
    +{channels,[]}
     7>

    See ssh_connection and ssh_connection:exec/4 for finding documentation of the channel messages.

    To collect the channel messages in a program, use receive...end instead of flush/1:

    5> receive
    -5>     {ssh_cm, ConnectionRef, {data, ChannelId, Type, Result}} when Type == 0 ->
    -5>         {ok,Result}
    -5>     {ssh_cm, ConnectionRef, {data, ChannelId, Type, Result}} when Type == 1 ->
    -5>         {error,Result}
    +5>     {ssh_cm, ConnectionRef, {data, ChannelId, Type, Result}} when Type == 0 ->
    +5>         {ok,Result}
    +5>     {ssh_cm, ConnectionRef, {data, ChannelId, Type, Result}} when Type == 1 ->
    +5>         {error,Result}
     5> end.
    -{ok,<<"/home/otptest\n">>}
    +{ok,<<"/home/otptest\n">>}
     6>

    Note that only the exec channel is closed after the one-time execution. The connection is still up and can handle previously opened channels. It is also possible to open a new channel:

    % try to open a new channel to check if the ConnectionRef is still open
    -7> {ok, NewChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    -{ok,1}
    +7> {ok, NewChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    +{ok,1}
     8>

    To close the connection, call the function ssh:close(ConnectionRef). As an alternative, set the option {idle_time, 1} when opening the @@ -100,23 +100,23 @@ "command" must be as if entered into the erlang shell, that is a sequence of Erlang expressions ended by a period (.). Variables bound in that sequence will keep their bindings throughout the expression -sequence. The bindings are disposed when the result is returned.

    Here is an example of a suitable expression sequence:

    A=1, B=2, 3 == (A + B).

    It evaluates to true if submitted to the Erlang daemon started in +sequence. The bindings are disposed when the result is returned.

    Here is an example of a suitable expression sequence:

    A=1, B=2, 3 == (A + B).

    It evaluates to true if submitted to the Erlang daemon started in Step 3 above:

    $bash> ssh ssh.example.com -p 8989 "A=1, B=2, 3 == (A + B)."
     true
     $bash>

    The same example but now using the Erlang ssh client to contact the Erlang -server:

    1> {ok, ConnectionRef} = ssh:connect("ssh.example.com", 8989, []).
    -{ok,<0.216.0>}
    -2> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    -{ok,0}
    -3> success = ssh_connection:exec(ConnectionRef, ChannelId,
    +server:

    1> {ok, ConnectionRef} = ssh:connect("ssh.example.com", 8989, []).
    +{ok,<0.216.0>}
    +2> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    +{ok,0}
    +3> success = ssh_connection:exec(ConnectionRef, ChannelId,
                                      "A=1, B=2, 3 == (A + B).",
    -                                 infinity).
    +                                 infinity).
     success
    -4> flush().
    -Shell got {ssh_cm,<0.216.0>,{data,0,0,<<"true">>}}
    -Shell got {ssh_cm,<0.216.0>,{exit_status,0,0}}
    -Shell got {ssh_cm,<0.216.0>,{eof,0}}
    -Shell got {ssh_cm,<0.216.0>,{closed,0}}
    +4> flush().
    +Shell got {ssh_cm,<0.216.0>,{data,0,0,<<"true">>}}
    +Shell got {ssh_cm,<0.216.0>,{exit_status,0,0}}
    +Shell got {ssh_cm,<0.216.0>,{eof,0}}
    +Shell got {ssh_cm,<0.216.0>,{closed,0}}
     ok
     5>

    Note that Erlang shell specific functions and control sequences like for example h(). are not supported.

    I/O from a function called in an Erlang ssh daemon

    Output to stdout on the server side is also displayed as well as the resulting @@ -131,36 +131,36 @@ write something: [a,b,c]. {ok,[a,b,c]} $bash>

    The same example but using the Erlang ssh client:

    
    -Eshell V10.5.2  (abort with ^G)
    -1> ssh:start().
    +Eshell V10.5.2  (abort with ^G)
    +1> ssh:start().
     ok
    -2> {ok, ConnectionRef} = ssh:connect(loopback, 8989, []).
    -{ok,<0.92.0>}
    -3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    -{ok,0}
    -4> success = ssh_connection:exec(ConnectionRef, ChannelId,
    +2> {ok, ConnectionRef} = ssh:connect(loopback, 8989, []).
    +{ok,<0.92.0>}
    +3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    +{ok,0}
    +4> success = ssh_connection:exec(ConnectionRef, ChannelId,
                                      "io:read(\"write something: \").",
    -                                 infinity).
    +                                 infinity).
     success
    -5> flush().
    -Shell got {ssh_cm,<0.92.0>,{data,0,0,<<"write something: ">>}}
    +5> flush().
    +Shell got {ssh_cm,<0.92.0>,{data,0,0,<<"write something: ">>}}
     ok
     % All data is sent as binaries with string contents:
    -6> ok = ssh_connection:send(ConnectionRef, ChannelId, <<"[a,b,c].">>).
    +6> ok = ssh_connection:send(ConnectionRef, ChannelId, <<"[a,b,c].">>).
     ok
    -7> flush().
    +7> flush().
     ok
     %% Nothing is received, because the io:read/1
     %% requires the input line to end with a newline.
     
     %% Send a newline (it could have been included in the last send):
    -8> ssh_connection:send(ConnectionRef, ChannelId, <<"\n">>).
    +8> ssh_connection:send(ConnectionRef, ChannelId, <<"\n">>).
     ok
    -9> flush().
    -Shell got {ssh_cm,<0.92.0>,{data,0,0,<<"{ok,[a,b,c]}">>}}
    -Shell got {ssh_cm,<0.92.0>,{exit_status,0,0}}
    -Shell got {ssh_cm,<0.92.0>,{eof,0}}
    -Shell got {ssh_cm,<0.92.0>,{closed,0}}
    +9> flush().
    +Shell got {ssh_cm,<0.92.0>,{data,0,0,<<"{ok,[a,b,c]}">>}}
    +Shell got {ssh_cm,<0.92.0>,{exit_status,0,0}}
    +Shell got {ssh_cm,<0.92.0>,{eof,0}}
    +Shell got {ssh_cm,<0.92.0>,{closed,0}}
     ok
     10>

    Configuring the server's (daemon's) command execution

    Every time a daemon is started, it enables one-time execution of commands as described in the @@ -171,44 +171,44 @@ ssh:daemon/2,3 and exec_daemon_option() for details.

    Examples of the two ways to configure the exec evaluator:

    1. Disable one-time execution.
      To modify the daemon start example above to reject one-time execution requests, we change Step 3 by adding the -option {exec, disabled} to:
    1> ssh:start().
    +option {exec, disabled} to:
    1> ssh:start().
     ok
    -2> {ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
    -                                  {user_dir, "/tmp/otptest_user/.ssh"},
    -                                  {exec, disabled}
    -                                 ]).
    -{ok,<0.54.0>}
    +2> {ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
    +                                  {user_dir, "/tmp/otptest_user/.ssh"},
    /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
    --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.html	2026-08-21 04:00:28.189351824 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh.html	2026-08-21 04:00:28.190351830 +0000
    @@ -2266,14 +2266,14 @@
     
     

    List of algorithms to use in the algorithm negotiation. The default algs_list/0 can be obtained from default_algorithms/0.

    If an alg_entry() is missing in the algs_list(), the default value is used for -that entry.

    Here is an example of this option:

    	  {preferred_algorithms,
    -	  [{public_key,['ssh-rsa','ssh-dss']},
    -	  {cipher,[{client2server,['aes128-ctr']},
    -          {server2client,['aes128-cbc','3des-cbc']}]},
    -	  {mac,['hmac-sha2-256','hmac-sha1']},
    -	  {compression,[none,zlib]}
    -	  ]
    -	  }

    The example specifies different algorithms in the two directions (client2server +that entry.

    Here is an example of this option:

    	  {preferred_algorithms,
    +	  [{public_key,['ssh-rsa','ssh-dss']},
    +	  {cipher,[{client2server,['aes128-ctr']},
    +          {server2client,['aes128-cbc','3des-cbc']}]},
    +	  {mac,['hmac-sha2-256','hmac-sha1']},
    +	  {compression,[none,zlib]}
    +	  ]
    +	  }

    The example specifies different algorithms in the two directions (client2server and server2client), for cipher but specifies the same algorithms for mac and compression in both directions. The kex (key exchange) is implicit but public_key is set explicitly.

    For background and more examples see the @@ -5516,21 +5516,21 @@

    hostkey_fingerprint([DigestType], HostKey) -> [string()]hostkey_fingerprint(DigestType, HostKey) -> string()

    Calculates a ssh fingerprint from a public host key as openssh does.

    The algorithm in hostkey_fingerprint/1 is md5 to be compatible with older ssh-keygen commands. The string from the second variant is -prepended by the algorithm name in uppercase as in newer ssh-keygen commands.

    Examples:

     2> ssh:hostkey_fingerprint(Key).
    +prepended by the algorithm name in uppercase as in newer ssh-keygen commands.

    Examples:

     2> ssh:hostkey_fingerprint(Key).
      "f5:64:a6:c1:5a:cb:9f:0a:10:46:a2:5c:3e:2f:57:84"
     
    - 3> ssh:hostkey_fingerprint(md5,Key).
    + 3> ssh:hostkey_fingerprint(md5,Key).
      "MD5:f5:64:a6:c1:5a:cb:9f:0a:10:46:a2:5c:3e:2f:57:84"
     
    - 4> ssh:hostkey_fingerprint(sha,Key).
    + 4> ssh:hostkey_fingerprint(sha,Key).
      "SHA1:bSLY/C4QXLDL/Iwmhyg0PGW9UbY"
     
    - 5> ssh:hostkey_fingerprint(sha256,Key).
    + 5> ssh:hostkey_fingerprint(sha256,Key).
      "SHA256:aZGXhabfbf4oxglxltItWeHU7ub3Dc31NcNw2cMJePQ"
     
    - 6> ssh:hostkey_fingerprint([sha,sha256],Key).
    - ["SHA1:bSLY/C4QXLDL/Iwmhyg0PGW9UbY",
    -  "SHA256:aZGXhabfbf4oxglxltItWeHU7ub3Dc31NcNw2cMJePQ"]
    +
    6> ssh:hostkey_fingerprint([sha,sha256],Key). + ["SHA1:bSLY/C4QXLDL/Iwmhyg0PGW9UbY", + "SHA256:aZGXhabfbf4oxglxltItWeHU7ub3Dc31NcNw2cMJePQ"]
    /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh_agent.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (983)) --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh_agent.html 2026-08-21 04:00:28.215351993 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/ssh_agent.html 2026-08-21 04:00:28.219352019 +0000 @@ -100,11 +100,11 @@ authentication.

    Ssh_agent implements the ssh_client_key_api, to allow it to be used by setting the option key_cb when starting a client (with for example ssh:connect, -ssh:shell ).

          {key_cb, {ssh_agent, []}}

    The agent communication is established through a UNIX domain socket. By default, +ssh:shell ).

          {key_cb, {ssh_agent, []}}

    The agent communication is established through a UNIX domain socket. By default, the socket path will be fetched from the SSH_AUTH_SOCK environment variable, which is the default socket path in the agent implementation of OpenSSH.

    In order to set a different socket path the socket_path -option can be set.

          {key_cb, {ssh_agent, [{socket_path, SocketPath}]}}

    Note

    The functions are Callbacks for the SSH app. They are not intended to be +option can be set.

          {key_cb, {ssh_agent, [{socket_path, SocketPath}]}}

    Note

    The functions are Callbacks for the SSH app. They are not intended to be called from the user's code!

    /usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/using_ssh.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (956)) --- old//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/using_ssh.html 2026-08-21 04:00:28.248352208 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssh-5.5.2.3/doc/html/using_ssh.html 2026-08-21 04:00:28.247352202 +0000 @@ -98,9 +98,9 @@ entering a password). Also, ssh.example.com is a known host in the known_hosts file of the user otptest. This means that host-verification can be done without user-interaction.

    Using the Erlang ssh Terminal Client

    The user otptest, which has bash as default shell, uses the ssh:shell/1 -client to connect to the OpenSSH daemon running on a host called ssh.example.com:

    1> ssh:start().
    +client to connect to the OpenSSH daemon running on a host called ssh.example.com:

    1> ssh:start().
     ok
    -2> {ok, S} = ssh:shell("ssh.example.com").
    +2> {ok, S} = ssh:shell("ssh.example.com").
     otptest@ssh.example.com:> pwd
     /home/otptest
     otptest@ssh.example.com:> exit
    @@ -113,11 +113,11 @@
     [...]
     $bash> ssh-keygen -t rsa -f /tmp/otptest_user/.ssh/id_rsa
     [...]

    Step 2. Create the file /tmp/otptest_user/.ssh/authorized_keys and add the -content of /tmp/otptest_user/.ssh/id_rsa.pub.

    Step 3. Start the Erlang ssh daemon:

    1> ssh:start().
    +content of /tmp/otptest_user/.ssh/id_rsa.pub.

    Step 3. Start the Erlang ssh daemon:

    1> ssh:start().
     ok
    -2> {ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
    -                                  {user_dir, "/tmp/otptest_user/.ssh"}]).
    -{ok,<0.54.0>}
    +2> {ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
    +                                  {user_dir, "/tmp/otptest_user/.ssh"}]).
    +{ok,<0.54.0>}
     3>

    Step 4. Use the OpenSSH client from a shell to connect to the Erlang ssh daemon:

    $bash> ssh ssh.example.com -p 8989  -i /tmp/otptest_user/.ssh/id_rsa \
                       -o UserKnownHostsFile=/tmp/otptest_user/.ssh/known_hosts
    @@ -128,42 +128,42 @@
     Eshell V5.10  (abort with ^G)
     1>

    There are two ways of shutting down an ssh daemon, see Step 5a and Step 5b.

    Step 5a. Shut down the Erlang ssh daemon so that it stops the listener but -leaves existing connections, started by the listener, operational:

    3> ssh:stop_listener(Sshd).
    +leaves existing connections, started by the listener, operational:

    3> ssh:stop_listener(Sshd).
     ok
     4>

    Step 5b. Shut down the Erlang ssh daemon so that it stops the listener and -all connections started by the listener:

    3> ssh:stop_daemon(Sshd).
    +all connections started by the listener:

    3> ssh:stop_daemon(Sshd).
     ok
     4>

    One-Time Execution

    Erlang client contacting OS standard ssh server

    In the following example, the Erlang shell is the client process that receives the channel replies as Erlang messages.

    Do an one-time execution of a remote OS command ("pwd") over ssh to the ssh -server of the OS at the host "ssh.example.com":

    1> ssh:start().
    +server of the OS at the host "ssh.example.com":

    1> ssh:start().
     ok
    -2> {ok, ConnectionRef} = ssh:connect("ssh.example.com", 22, []).
    -{ok,<0.57.0>}
    -3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    -{ok,0}
    -4> success = ssh_connection:exec(ConnectionRef, ChannelId, "pwd", infinity).
    -5> flush(). % Get all pending messages. NOTE: ordering may vary!
    -Shell got {ssh_cm,<0.57.0>,{data,0,0,<<"/home/otptest\n">>}}
    -Shell got {ssh_cm,<0.57.0>,{eof,0}}
    -Shell got {ssh_cm,<0.57.0>,{exit_status,0,0}}
    -Shell got {ssh_cm,<0.57.0>,{closed,0}}
    +2> {ok, ConnectionRef} = ssh:connect("ssh.example.com", 22, []).
    +{ok,<0.57.0>}
    +3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    +{ok,0}
    +4> success = ssh_connection:exec(ConnectionRef, ChannelId, "pwd", infinity).
    +5> flush(). % Get all pending messages. NOTE: ordering may vary!
    +Shell got {ssh_cm,<0.57.0>,{data,0,0,<<"/home/otptest\n">>}}
    +Shell got {ssh_cm,<0.57.0>,{eof,0}}
    +Shell got {ssh_cm,<0.57.0>,{exit_status,0,0}}
    +Shell got {ssh_cm,<0.57.0>,{closed,0}}
     ok
    -6> ssh:connection_info(ConnectionRef, channels).
    -{channels,[]}
    +6> ssh:connection_info(ConnectionRef, channels).
    +{channels,[]}
     7>

    See ssh_connection and ssh_connection:exec/4 for finding documentation of the channel messages.

    To collect the channel messages in a program, use receive...end instead of flush/1:

    5> receive
    -5>     {ssh_cm, ConnectionRef, {data, ChannelId, Type, Result}} when Type == 0 ->
    -5>         {ok,Result}
    -5>     {ssh_cm, ConnectionRef, {data, ChannelId, Type, Result}} when Type == 1 ->
    -5>         {error,Result}
    +5>     {ssh_cm, ConnectionRef, {data, ChannelId, Type, Result}} when Type == 0 ->
    +5>         {ok,Result}
    +5>     {ssh_cm, ConnectionRef, {data, ChannelId, Type, Result}} when Type == 1 ->
    +5>         {error,Result}
     5> end.
    -{ok,<<"/home/otptest\n">>}
    +{ok,<<"/home/otptest\n">>}
     6>

    Note that only the exec channel is closed after the one-time execution. The connection is still up and can handle previously opened channels. It is also possible to open a new channel:

    % try to open a new channel to check if the ConnectionRef is still open
    -7> {ok, NewChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    -{ok,1}
    +7> {ok, NewChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    +{ok,1}
     8>

    To close the connection, call the function ssh:close(ConnectionRef). As an alternative, set the option {idle_time, 1} when opening the @@ -172,23 +172,23 @@ "command" must be as if entered into the erlang shell, that is a sequence of Erlang expressions ended by a period (.). Variables bound in that sequence will keep their bindings throughout the expression -sequence. The bindings are disposed when the result is returned.

    Here is an example of a suitable expression sequence:

    A=1, B=2, 3 == (A + B).

    It evaluates to true if submitted to the Erlang daemon started in +sequence. The bindings are disposed when the result is returned.

    Here is an example of a suitable expression sequence:

    A=1, B=2, 3 == (A + B).

    It evaluates to true if submitted to the Erlang daemon started in Step 3 above:

    $bash> ssh ssh.example.com -p 8989 "A=1, B=2, 3 == (A + B)."
     true
     $bash>

    The same example but now using the Erlang ssh client to contact the Erlang -server:

    1> {ok, ConnectionRef} = ssh:connect("ssh.example.com", 8989, []).
    -{ok,<0.216.0>}
    -2> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    -{ok,0}
    -3> success = ssh_connection:exec(ConnectionRef, ChannelId,
    +server:

    1> {ok, ConnectionRef} = ssh:connect("ssh.example.com", 8989, []).
    +{ok,<0.216.0>}
    +2> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    +{ok,0}
    +3> success = ssh_connection:exec(ConnectionRef, ChannelId,
                                      "A=1, B=2, 3 == (A + B).",
    -                                 infinity).
    +                                 infinity).
     success
    -4> flush().
    -Shell got {ssh_cm,<0.216.0>,{data,0,0,<<"true">>}}
    -Shell got {ssh_cm,<0.216.0>,{exit_status,0,0}}
    -Shell got {ssh_cm,<0.216.0>,{eof,0}}
    -Shell got {ssh_cm,<0.216.0>,{closed,0}}
    +4> flush().
    +Shell got {ssh_cm,<0.216.0>,{data,0,0,<<"true">>}}
    +Shell got {ssh_cm,<0.216.0>,{exit_status,0,0}}
    +Shell got {ssh_cm,<0.216.0>,{eof,0}}
    +Shell got {ssh_cm,<0.216.0>,{closed,0}}
     ok
     5>

    Note that Erlang shell specific functions and control sequences like for example h(). are not supported.

    I/O from a function called in an Erlang ssh daemon

    Output to stdout on the server side is also displayed as well as the resulting @@ -203,36 +203,36 @@ write something: [a,b,c]. {ok,[a,b,c]} $bash>

    The same example but using the Erlang ssh client:

    
    -Eshell V10.5.2  (abort with ^G)
    -1> ssh:start().
    +Eshell V10.5.2  (abort with ^G)
    +1> ssh:start().
     ok
    -2> {ok, ConnectionRef} = ssh:connect(loopback, 8989, []).
    -{ok,<0.92.0>}
    -3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    -{ok,0}
    -4> success = ssh_connection:exec(ConnectionRef, ChannelId,
    +2> {ok, ConnectionRef} = ssh:connect(loopback, 8989, []).
    +{ok,<0.92.0>}
    +3> {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity).
    +{ok,0}
    +4> success = ssh_connection:exec(ConnectionRef, ChannelId,
                                      "io:read(\"write something: \").",
    -                                 infinity).
    +                                 infinity).
     success
    -5> flush().
    -Shell got {ssh_cm,<0.92.0>,{data,0,0,<<"write something: ">>}}
    +5> flush().
    +Shell got {ssh_cm,<0.92.0>,{data,0,0,<<"write something: ">>}}
     ok
     % All data is sent as binaries with string contents:
    -6> ok = ssh_connection:send(ConnectionRef, ChannelId, <<"[a,b,c].">>).
    +6> ok = ssh_connection:send(ConnectionRef, ChannelId, <<"[a,b,c].">>).
     ok
    -7> flush().
    +7> flush().
     ok
     %% Nothing is received, because the io:read/1
     %% requires the input line to end with a newline.
     
     %% Send a newline (it could have been included in the last send):
    -8> ssh_connection:send(ConnectionRef, ChannelId, <<"\n">>).
    +8> ssh_connection:send(ConnectionRef, ChannelId, <<"\n">>).
     ok
    -9> flush().
    -Shell got {ssh_cm,<0.92.0>,{data,0,0,<<"{ok,[a,b,c]}">>}}
    -Shell got {ssh_cm,<0.92.0>,{exit_status,0,0}}
    -Shell got {ssh_cm,<0.92.0>,{eof,0}}
    -Shell got {ssh_cm,<0.92.0>,{closed,0}}
    +9> flush().
    +Shell got {ssh_cm,<0.92.0>,{data,0,0,<<"{ok,[a,b,c]}">>}}
    +Shell got {ssh_cm,<0.92.0>,{exit_status,0,0}}
    +Shell got {ssh_cm,<0.92.0>,{eof,0}}
    +Shell got {ssh_cm,<0.92.0>,{closed,0}}
     ok
     10>

    Configuring the server's (daemon's) command execution

    Every time a daemon is started, it enables one-time execution of commands as described in the @@ -243,44 +243,44 @@ ssh:daemon/2,3 and exec_daemon_option() for details.

    Examples of the two ways to configure the exec evaluator:

    1. Disable one-time execution.
      To modify the daemon start example above to reject one-time execution requests, we change Step 3 by adding the -option {exec, disabled} to:
    1> ssh:start().
    +option {exec, disabled} to:
    1> ssh:start().
     ok
    -2> {ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
    -                                  {user_dir, "/tmp/otptest_user/.ssh"},
    -                                  {exec, disabled}
    -                                 ]).
    -{ok,<0.54.0>}
    +2> {ok, Sshd} = ssh:daemon(8989, [{system_dir, "/tmp/ssh_daemon"},
    +                                  {user_dir, "/tmp/otptest_user/.ssh"},
    /usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text)
    --- old//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub/OEBPS/content.opf	2026-08-05 05:56:49.000000000 +0000
    @@ -4,10 +4,10 @@
              version="3.0">
       
         ssl - 11.6.0.4
    -    urn:uuid:c52597a5-59aa-67f5-f0c2-2232064e25a0
    +    urn:uuid:69fb3da7-a859-7e18-1d15-87b6b4dc3569
         en
     
    -    2026-08-21T03:49:39Z
    +    2042-09-22T17:08:39Z
     
       
       
    /usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub/OEBPS/ssl_distribution.xhtml differs (HTML document, ASCII text, with very long lines (1021))
    --- old//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub/OEBPS/ssl_distribution.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub/OEBPS/ssl_distribution.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -33,14 +33,14 @@
     applications. Such a script is located in the bin directory of the Erlang
     distribution. The source for the script is found under the Erlang installation
     top directory under releases/<OTP version>/start_clean.rel.

    Do the following:

    • Copy that script to another location (and preferably another name).
    • Add the applications Crypto, Public Key, and SSL with their current version -numbers after the STDLIB application.

    The following shows an example .rel file with TLS added:

          {release, {"OTP  APN 181 01","R15A"}, {erts, "5.9"},
    -      [{kernel,"2.15"},
    -      {stdlib,"1.18"},
    -      {crypto, "2.0.3"},
    -      {public_key, "0.12"},
    -      {asn1, "4.0"},
    -      {ssl, "5.0"}
    -      ]}.

    The version numbers differ in your system. Whenever one of the applications +numbers after the STDLIB application.

    The following shows an example .rel file with TLS added:

          {release, {"OTP  APN 181 01","R15A"}, {erts, "5.9"},
    +      [{kernel,"2.15"},
    +      {stdlib,"1.18"},
    +      {crypto, "2.0.3"},
    +      {public_key, "0.12"},
    +      {asn1, "4.0"},
    +      {ssl, "5.0"}
    +      ]}.

    The version numbers differ in your system. Whenever one of the applications included in the script is upgraded, change the script.

    Do the following:

    • Build the boot script.

      Assuming the .rel file is stored in a file start_ssl.rel in the current directory, a boot script can be built as follows:

       1> systools:make_script("start_ssl",[]).

    There is now a start_ssl.boot file in the current directory.

    Do the following:

    • Test the boot script. To do this, start Erlang with the -boot command-line parameter specifying this boot script (with its full path, but without the @@ -75,10 +75,10 @@ so beware!

    For TLS to work, at least a public key and a certificate must be specified for the server side and the client needs to specify CAs that it trusts (client certification is optional and requires more configuration).

    In the following example (to keep it simple), the PEM file "/home/me/ssl/erlserver.pem" -contains both the server certificate and its private key .

    Create a file named for example "/home/me/ssl/ssl_test@myhost.conf":

    [{server,
    -  [{certfile, "/home/me/ssl/erlserver.pem"}]},
    - {client,
    -  [{cacertfile, "/home/me/ssl/client_trusted.pem"}]}].

    And then start the node like this (line breaks in the command are for +contains both the server certificate and its private key .

    Create a file named for example "/home/me/ssl/ssl_test@myhost.conf":

    [{server,
    +  [{certfile, "/home/me/ssl/erlserver.pem"}]},
    + {client,
    +  [{cacertfile, "/home/me/ssl/client_trusted.pem"}]}].

    And then start the node like this (line breaks in the command are for readability, and shall not be there when typed):

    $ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls
       -ssl_dist_optfile "/home/me/ssl/ssl_test@myhost.conf"
       -sname ssl_test

    The options in the {server, Opts} tuple are used when calling @@ -96,25 +96,25 @@ present any certificate.

    A node started in this way is fully functional, using TLS as the distribution protocol.

    verify_fun Configuration Example

    The verify_fun option creates a reference to the implementing function since the configuration is evaluated as an Erlang term. In -an example file for use with -ssl_dist_optfile:

    [{server,[{fail_if_no_peer_cert,true},
    -          {certfile,"/home/me/ssl/cert.pem"},
    -          {keyfile,"/home/me/ssl/privkey.pem"},
    -          {cacertfile,"/home/me/ssl/ca_cert.pem"},
    -          {verify,verify_peer},
    -          {verify_fun,{fun mydist:verify/3,"any initial value"}}]},
    - {client,[{certfile,"/home/me/ssl/cert.pem"},
    -          {keyfile,"/home/me/ssl/privkey.pem"},
    -          {cacertfile,"/home/me/ssl/ca_cert.pem"},
    -          {verify,verify_peer},
    -          {verify_fun,{fun mydist:verify/3,"any initial value"}}]}].
    -

    mydist:verify/3 will be called with:

    • OtpCert, the other party's certificate PKIX Certificates
    • SslStatus, OTP's verification outcome, such as valid or a tuple {bad_cert, unknown_ca}
    • Init will be "any initial value"

    A pattern for verify/3 will look like:

    verify(OtpCert, _SslStatus, Init) ->
    -    IsOk = is_ok(OtpCert, Init),
    +an example file for use with -ssl_dist_optfile:

    [{server,[{fail_if_no_peer_cert,true},
    +          {certfile,"/home/me/ssl/cert.pem"},
    +          {keyfile,"/home/me/ssl/privkey.pem"},
    +          {cacertfile,"/home/me/ssl/ca_cert.pem"},
    +          {verify,verify_peer},
    +          {verify_fun,{fun mydist:verify/3,"any initial value"}}]},
    + {client,[{certfile,"/home/me/ssl/cert.pem"},
    +          {keyfile,"/home/me/ssl/privkey.pem"},
    +          {cacertfile,"/home/me/ssl/ca_cert.pem"},
    +          {verify,verify_peer},
    +          {verify_fun,{fun mydist:verify/3,"any initial value"}}]}].
    +

    mydist:verify/3 will be called with:

    • OtpCert, the other party's certificate PKIX Certificates
    • SslStatus, OTP's verification outcome, such as valid or a tuple {bad_cert, unknown_ca}
    • Init will be "any initial value"

    A pattern for verify/3 will look like:

    verify(OtpCert, _SslStatus, Init) ->
    +    IsOk = is_ok(OtpCert, Init),
         NewInitValue = "some new value",
         case IsOk of
            true ->
    -           {valid, NewInitValue};
    +           {valid, NewInitValue};
            false ->
    -           {failure, NewInitValue}
    +           {failure, NewInitValue}
         end.

    verify_fun can accept a verify/4 function, which will receive:

    • OtpCert, the other party's certificate PKIX Certificates
    • DerCert, the other party's original DER Encoded certificate
    • SslStatus, OTP's verification outcome, such as valid or a tuple {bad_cert, unknown_ca}
    • Init will be "any initial value"

    The verify/4 can use the DerCert for atypical workarounds such as handling decoding errors and directly verifying signatures.

    For more details see {verify_fun, Verify} in common_option_cert

    Note

    The legacy command line format for verify_fun cannot be used in a -ssl_dist_optfile file as described below in @@ -154,19 +154,19 @@ -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] +Erlang (BEAM) emulator version 5.0 [source] -Eshell V5.0 (abort with ^G) -(ssl_test@myhost)1> init:get_arguments(). -[{root,["/usr/local/erlang"]}, - {progname,["erl "]}, - {sname,["ssl_test"]}, - {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"] - {home,["/home/me"]}]

    The init:get_arguments() call verifies that the correct arguments are supplied +Eshell V5.0 (abort with ^G) +(ssl_test@myhost)1> init:get_arguments(). +[{root,["/usr/local/erlang"]}, + {progname,["erl "]}, + {sname,["ssl_test"]}, + {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"] + {home,["/home/me"]}]

    The init:get_arguments() call verifies that the correct arguments are supplied to the emulator.

    /usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub/OEBPS/ssl.xhtml differs (HTML document, ASCII text, with very long lines (1026)) --- old//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub/OEBPS/ssl.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub/OEBPS/ssl.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -25,9 +25,9 @@

    Interface functions for TLS (Transport Layer Security) and DTLS (Datagram Transport Layer Security).

    Note

    The application's name is still SSL because the first versions of the TLS protocol were named SSL (Secure Socket Layer). However, no version -of the old SSL protocol is supported by this application.

    Example:

    1> ssl:start(), ssl:connect("google.com", 443, [{verify, verify_peer},
    -    {cacerts, public_key:cacerts_get()}]).
    -{ok,{sslsocket, [...]}}

    See Examples for detailed usage and more examples of +of the old SSL protocol is supported by this application.

    Example:

    1> ssl:start(), ssl:connect("google.com", 443, [{verify, verify_peer},
    +    {cacerts, public_key:cacerts_get()}]).
    +{ok,{sslsocket, [...]}}

    See Examples for detailed usage and more examples of this API.

    Special Erlang node configuration for the application can be found in SSL Application.

    @@ -1897,26 +1897,26 @@ signature schemes supplied by the signature_algs_cert option.

    The TLS-1.2 default is Default_TLS_12_Alg_Pairs interleaved with rsa_pss_schemes since ssl-11.0 (Erlang/OTP 25). pss_pss is -preferred over pss_rsae, which in turn is preferred over rsa.

    The list for Default_TLS_12_Alg_Pairs is defined as follows:

    [
    -{sha512, ecdsa},
    -{sha512, rsa},
    -{sha384, ecdsa},
    -{sha384, rsa},
    -{sha256, ecdsa},
    -{sha256, rsa}
    -]

    Change

    • Support for {md5, rsa} was removed from the TLS-1.2 default in +preferred over pss_rsae, which in turn is preferred over rsa.

      The list for Default_TLS_12_Alg_Pairs is defined as follows:

      [
      +{sha512, ecdsa},
      +{sha512, rsa},
      +{sha384, ecdsa},
      +{sha384, rsa},
      +{sha256, ecdsa},
      +{sha256, rsa}
      +]

      Change

      • Support for {md5, rsa} was removed from the TLS-1.2 default in ssl-8.0 (Erlang/OTP 22).
      • Support for {sha, _} (SHA1) and {sha224, _} was removed -from the TLS-1.2 default in ssl-11.0 (Erlang/OTP 26).

      The list for rsa_pss_schemes is defined as follows:

      [rsa_pss_pss_sha512,
      +from the TLS-1.2 default in ssl-11.0 (Erlang/OTP 26).

    The list for rsa_pss_schemes is defined as follows:

    [rsa_pss_pss_sha512,
     rsa_pss_pss_sha384,
     rsa_pss_pss_sha256,
     rsa_pss_rsae_sha512,
     rsa_pss_rsae_sha384,
    -rsa_pss_rsae_sha256]

    The list of TLS_13_Legacy_Schemes is defined as follows:

    [
    +rsa_pss_rsae_sha256]

    The list of TLS_13_Legacy_Schemes is defined as follows:

    [
     %% Legacy algorithms only applicable to certificate signatures
     rsa_pkcs1_sha512, %% Corresponds to {sha512, rsa}
     rsa_pkcs1_sha384, %% Corresponds to {sha384, rsa}
     rsa_pkcs1_sha256, %% Corresponds to {sha256, rsa}
    -]

    The list of Default_TLS_13_Schemes is defined as follows:

    [
    +]

    The list of Default_TLS_13_Schemes is defined as follows:

    [
     %% EDDSA
     eddsa_ed25519,
     eddsa_ed448
    @@ -2225,8 +2225,8 @@
     
           
     
    -

    Claim an intermediate CA in the chain as trusted.

    fun(Chain::[public_key:der_encoded()]) ->
    -      {trusted_ca, DerCert::public_key:der_encoded()} | unknown_ca.

    TLS then uses public_key:pkix_path_validation/3 with the selected CA +

    Claim an intermediate CA in the chain as trusted.

    fun(Chain::[public_key:der_encoded()]) ->
    +      {trusted_ca, DerCert::public_key:der_encoded()} | unknown_ca.

    TLS then uses public_key:pkix_path_validation/3 with the selected CA as the trusted anchor and verifies the rest of the chain.

    @@ -2480,7 +2480,7 @@ being sent and disables the hostname verification check.

  • {customize_hostname_check, HostNameCheckOpts} - Customization option

    Customizes the hostname verification of the peer certificate, as various protocols that use TLS, such as HTTP or LDAP, may require different approaches. For example, here is how to use standard hostname checking for HTTPS implemented in -Public_Key:

    {customize_hostname_check, [{match_fun, public_key:pkix_verify_hostname_match_fun(https)}]}

    For futher description of the customize options, see +Public_Key:

    {customize_hostname_check, [{match_fun, public_key:pkix_verify_hostname_match_fun(https)}]}

    For futher description of the customize options, see public_key:pkix_verify_hostname/3.

  • {client_certificate_authorities, UseCertAuth} - Inter-op hint option

    If UseCertAuth is set to true, sends the certificate authorities extension in the TLS-1.3 client hello. The default is false. Note that setting UseCertAuth to true can result in a significant @@ -2496,21 +2496,21 @@ OCSP query or a CRL check. Note however that accepting {bad_cert, missing_ocsp_staple} without performing alternative revocation checking is insecure, as it allows a MITM attacker to -suppress revocation information by omitting the OCSP staple.

    {verify_fun, {fun(_, _, {bad_cert, missing_ocsp_staple} = R, _St) ->
    +suppress revocation information by omitting the OCSP staple.

    {verify_fun, {fun(_, _, {bad_cert, missing_ocsp_staple} = R, _St) ->
                           %% Implement fallback revocation check here,
                           %% e.g. a direct OCSP query or CRL check.
                           %% Simply returning {valid, St} skips
                           %% revocation checking entirely.
    -                      {fail, R};
    -                 (_, _, {bad_cert, _} = R, _) ->
    -                      {fail, R};
    -                 (_, _, {extension, _}, St) ->
    -                      {unknown, St};
    -                 (_, _, valid, St) ->
    -                      {valid, St};
    -                 (_, _, valid_peer, St) ->
    -                      {valid, St}
    -              end, []}}

    When Stapling is given as a map, boolean ocsp_nonce key can + {fail, R}; + (_, _, {bad_cert, _} = R, _) -> + {fail, R}; + (_, _, {extension, _}, St) -> + {unknown, St}; + (_, _, valid, St) -> + {valid, St}; + (_, _, valid_peer, St) -> + {valid, St} + end, []}}

    When Stapling is given as a map, boolean ocsp_nonce key can indicate whether an OCSP nonce should be requested by the client (default is false).

    Note

    The OCSP response can be provided without a nonce value — even if it was requested by the client. In such cases SSL will proceed with the handshake and generate @@ -2643,7 +2643,7 @@

    Options only relevant for TLS-1.3.

    • {session_tickets, SessionTickets} - Use of session tickets

      Configures the session ticket functionality. Allowed values are disabled, manual, and auto. If it is set to manual the client will send the ticket -information to user process in a 3-tuple:

      {ssl, session_ticket, `Ticket::`(`t:session_ticket/0`)}

      where Ticket is a map with information about the created TLS-1.3 session ticket. +information to user process in a 3-tuple:

      {ssl, session_ticket, `Ticket::`(`t:session_ticket/0`)}

      where Ticket is a map with information about the created TLS-1.3 session ticket. The only key that the user needs to consider is sni key to be able to provide it as a value in the use_ticket option list of possible tickets to use it to attempt session resumption to a server identified by the @@ -2656,7 +2656,7 @@ mandatory option in manual mode ({session_tickets, manual}).

      Note

      Session tickets are only sent to the user if option session_tickets is set to manual

      This option is supported by TLS-1.3. See also SSL User's Guide, Session Tickets and Session Resumption in TLS 1.3.

    • {early_data, EarlyData}

      Configures the early data to be sent by the client.

      To verify that the server has the intention to process the early -data, the following tuple is sent to the user process:

      {ssl, SslSocket, {early_data, Result}}

      where Result is either accepted or rejected.

      Warning

      It is the responsibility of the user to handle rejected EarlyData and to +data, the following tuple is sent to the user process:

      {ssl, SslSocket, {early_data, Result}}

      where Result is either accepted or rejected.

      Warning

      It is the responsibility of the user to handle rejected EarlyData and to resend when appropriate.

    • {middlebox_comp_mode, MiddleBoxMode}

      Configures the middlebox compatibility mode for a TLS-1.3 connection.

      A significant number of middleboxes misbehave when a TLS-1.3 connection is negotiated. Implementations can increase the chance of making connections through those middleboxes by adapting the TLS-1.3 @@ -2840,20 +2840,20 @@ peer certificate in a valid certification path. So, if depth is 0 the PEER must be signed by the trusted ROOT-CA directly; if 1 the path can be PEER, CA, ROOT-CA; if 2 the path can be PEER, CA, CA, ROOT-CA, and so on. The default -value is 10. Used to mitigate DoS attack possibilities.

    • {verify_fun, Verify} - Customize certificate path validation

      The verification fun is to be defined as follows:

      fun(OtpCert :: #'OTPCertificate'{},
      -    Event, InitialUserState :: term()) ->
      -  {valid, UserState :: term()} |
      -  {fail, Reason :: term()} | {unknown, UserState :: term()}.
      -
      -fun(OtpCert :: #'OTPCertificate'{}, DerCert :: public_key:der_encoded(),
      -    Event, InitialUserState :: term()) ->
      -  {valid, UserState :: term()} |
      -  {fail, Reason :: term()} | {unknown, UserState :: term()}.
      +value is 10. Used to mitigate DoS attack possibilities.

    • {verify_fun, Verify} - Customize certificate path validation

      The verification fun is to be defined as follows:

      fun(OtpCert :: #'OTPCertificate'{},
      +    Event, InitialUserState :: term()) ->
      +  {valid, UserState :: term()} |
      +  {fail, Reason :: term()} | {unknown, UserState :: term()}.
      +
      +fun(OtpCert :: #'OTPCertificate'{}, DerCert :: public_key:der_encoded(),
      +    Event, InitialUserState :: term()) ->
      +  {valid, UserState :: term()} |
      +  {fail, Reason :: term()} | {unknown, UserState :: term()}.
       
       Types:
      -      Event = {bad_cert, Reason :: atom() |
      -              {revoked, atom()}} |
      -      {extension, #'Extension'{}} |
      +      Event = {bad_cert, Reason :: atom() |
      +              {revoked, atom()}} |
      +      {extension, #'Extension'{}} |
                     valid |
                     valid_peer

      The verification fun is called during the X.509-path validation when an error occurs or an extension unknown to the SSL application is @@ -2870,25 +2870,25 @@ handshake does not terminate regardless of verification failures, and the connection is established.

    • If called with an extension unknown to the user application, the fun is to return {unknown, UserState}.

    Note that if the fun returns unknown for an extension marked as critical, -validation will fail.

    Default option verify_fun in verify_peer mode:

    {fun(_, _, {bad_cert, _} = Reason, _) ->
    -   {fail, Reason};
    -    (_, _, {extension, _}, UserState) ->
    -   {unknown, UserState};
    -    (_, _, valid, UserState) ->
    -   {valid, UserState};
    -    (_, _, valid_peer, UserState) ->
    -       {valid, UserState}
    - end, []}

    Default option verify_fun in mode verify_none:

     {fun(_, _, {bad_cert, _}, UserState) ->
    -   {valid, UserState};
    -    (_, _, {extension, #'Extension'{critical = true}}, UserState) ->
    -   {valid, UserState};
    -    (_, _, {extension, _}, UserState) ->
    -   {unknown, UserState};
    -    (_, _, valid, UserState) ->
    -   {valid, UserState};
    -    (_, _, valid_peer, UserState) ->
    -       {valid, UserState}
    - end, []}

    The possible path validation errors are given in the form {bad_cert, Reason}, +validation will fail.

    Default option verify_fun in verify_peer mode:

    {fun(_, _, {bad_cert, _} = Reason, _) ->
    +   {fail, Reason};
    +    (_, _, {extension, _}, UserState) ->
    +   {unknown, UserState};
    +    (_, _, valid, UserState) ->
    +   {valid, UserState};
    +    (_, _, valid_peer, UserState) ->
    +       {valid, UserState}
    + end, []}

    Default option verify_fun in mode verify_none:

     {fun(_, _, {bad_cert, _}, UserState) ->
    +   {valid, UserState};
    +    (_, _, {extension, #'Extension'{critical = true}}, UserState) ->
    +   {valid, UserState};
    +    (_, _, {extension, _}, UserState) ->
    +   {unknown, UserState};
    +    (_, _, valid, UserState) ->
    +   {valid, UserState};
    +    (_, _, valid_peer, UserState) ->
    +       {valid, UserState}
    + end, []}

    The possible path validation errors are given in the form {bad_cert, Reason}, where Reason is:

    • unknown_ca

      No trusted CA was found in the trusted store. The trusted /usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub/OEBPS/using_ssl.xhtml differs (HTML document, ASCII text, with very long lines (2124)) --- old//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub/OEBPS/using_ssl.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.epub/OEBPS/using_ssl.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -35,87 +35,87 @@ except for the purpose of pattern matching.

      Note

      Note that client certificate verification is optional for the server and needs additional conguration on both sides to work. The Certificate and keys, in the examples, are provided using the ssl:cert_key_conf/0 supplied in the certs_keys -introduced in OTP 25.

      Basic Client

       1 > ssl:start(), ssl:connect("google.com", 443, [{verify, verify_peer},
      -                                                 {cacerts, public_key:cacerts_get()}]).
      -   {ok,{sslsocket, [...]}}

      Basic Connection

      Step 1: Start the server side:

      1 server> ssl:start().
      +introduced in OTP 25.

    Basic Client

     1 > ssl:start(), ssl:connect("google.com", 443, [{verify, verify_peer},
    +                                                 {cacerts, public_key:cacerts_get()}]).
    +   {ok,{sslsocket, [...]}}

    Basic Connection

    Step 1: Start the server side:

    1 server> ssl:start().
     ok

    Step 2: with alternative certificates, in this example the EDDSA certificate will be preferred if TLS-1.3 is negotiated and the RSA certificate will always -be used for TLS-1.2 as it does not support the EDDSA algorithm:

    2 server> {ok, ListenSocket} =
    -ssl:listen(9999, [{certs_keys, [#{certfile => "eddsacert.pem",
    -                                  keyfile => "eddsakey.pem"},
    -                                #{certfile => "rsacert.pem",
    +be used for TLS-1.2 as it does not support the EDDSA algorithm:

    2 server> {ok, ListenSocket} =
    +ssl:listen(9999, [{certs_keys, [#{certfile => "eddsacert.pem",
    +                                  keyfile => "eddsakey.pem"},
    +                                #{certfile => "rsacert.pem",
                                       keyfile => "rsakey.pem",
    -                                  password => "foobar"}
    -                               ]},{reuseaddr, true}]).
    -{ok,{sslsocket, [...]}}

    Step 3: Do a transport accept on the TLS listen socket:

    3 server> {ok, TLSTransportSocket} = ssl:transport_accept(ListenSocket).
    -{ok,{sslsocket, [...]}}

    Note

    ssl:transport_accept/1 and ssl:handshake/2 are separate functions so that the + password => "foobar"} + ]},{reuseaddr, true}]). +{ok,{sslsocket, [...]}}

    Step 3: Do a transport accept on the TLS listen socket:

    3 server> {ok, TLSTransportSocket} = ssl:transport_accept(ListenSocket).
    +{ok,{sslsocket, [...]}}

    Note

    ssl:transport_accept/1 and ssl:handshake/2 are separate functions so that the handshake part can be called in a new Erlang process dedicated to handling the -connection

    Step 4: Start the client side:

    1 client> ssl:start().
    +connection

    Step 4: Start the client side:

    1 client> ssl:start().
     ok

    Be sure to configure trusted certificates to use for server certificate -verification.

    2 client> {ok, Socket} = ssl:connect("localhost", 9999,
    -      [{verify, verify_peer},
    -      {cacertfile, "cacerts.pem"}, {active, once}], infinity).
    -{ok,{sslsocket, [...]}}

    Step 5: Do the TLS handshake:

    4 server> {ok, Socket} = ssl:handshake(TLSTransportSocket).
    -{ok,{sslsocket, [...]}}

    Note

    A real server should use ssl:handshake/2, which accepts a timeout, to avoid DoS -attacks. In the example the timeout defaults to infinity.

    Step 6: Send a message over TLS:

    5 server> ssl:send(Socket, "foo").
    +verification.

    2 client> {ok, Socket} = ssl:connect("localhost", 9999,
    +      [{verify, verify_peer},
    +      {cacertfile, "cacerts.pem"}, {active, once}], infinity).
    +{ok,{sslsocket, [...]}}

    Step 5: Do the TLS handshake:

    4 server> {ok, Socket} = ssl:handshake(TLSTransportSocket).
    +{ok,{sslsocket, [...]}}

    Note

    A real server should use ssl:handshake/2, which accepts a timeout, to avoid DoS +attacks. In the example the timeout defaults to infinity.

    Step 6: Send a message over TLS:

    5 server> ssl:send(Socket, "foo").
     ok

    Step 7: Flush the shell message queue to see that the message sent on the -server side is recived by the client side:

    3 client> flush().
    -Shell got {ssl,{sslsocket,[...]},"foo"}
    +server side is recived by the client side:

    3 client> flush().
    +Shell got {ssl,{sslsocket,[...]},"foo"}
     ok

    Upgrade Example - TLS only

    Upgrading a a TCP/IP connection to a TLS connections is mostly used when there is a desire have unencrypted communication first and then later secure the communication channel by using TLS. Note that the client and server need to agree to do the upgrade in the protocol doing the communication. This is concept is often referenced as STARTLS and used in many protocols such as SMTP, -FTPS and HTTPS via a proxy.

    Warning

    Maximum security recommendations are however moving away from such solutions.

    To upgrade to a TLS connection:

    Step 1: Start the server side:

    1 server> ssl:start().
    +FTPS and HTTPS via a proxy.

    Warning

    Maximum security recommendations are however moving away from such solutions.

    To upgrade to a TLS connection:

    Step 1: Start the server side:

    1 server> ssl:start().
       ok

    Step 2: Create a normal TCP listen socket and ensure active is set to false and not set to any active mode otherwise TLS handshake messages can be -delivered to the wrong process.

    2 server> {ok, ListenSocket} = gen_tcp:listen(9999, [{reuseaddr, true},
    -  {active, false}]).
    -  {ok, #Port<0.475>}

    Step 3: Accept client connection:

    3 server> {ok, Socket} = gen_tcp:accept(ListenSocket).
    -  {ok, #Port<0.476>}

    Step 4: Start the client side:

    1 client> ssl:start().
    -  ok
    2 client> {ok, Socket} = gen_tcp:connect("localhost", 9999,  [], infinity).

    Step 5: Do the TLS handshake:

    4 server> {ok, TLSSocket} = ssl:handshake(Socket, [{verify, verify_peer},
    -  {fail_if_no_peer_cert, true},
    -  {cacertfile, "cacerts.pem"},
    -  {certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]}]).
    -  {ok,{sslsocket,[...]}}

    Step 6: Upgrade to a TLS connection. The client and server must agree upon the +delivered to the wrong process.

    2 server> {ok, ListenSocket} = gen_tcp:listen(9999, [{reuseaddr, true},
    +  {active, false}]).
    +  {ok, #Port<0.475>}

    Step 3: Accept client connection:

    3 server> {ok, Socket} = gen_tcp:accept(ListenSocket).
    +  {ok, #Port<0.476>}

    Step 4: Start the client side:

    1 client> ssl:start().
    +  ok
    2 client> {ok, Socket} = gen_tcp:connect("localhost", 9999,  [], infinity).

    Step 5: Do the TLS handshake:

    4 server> {ok, TLSSocket} = ssl:handshake(Socket, [{verify, verify_peer},
    +  {fail_if_no_peer_cert, true},
    +  {cacertfile, "cacerts.pem"},
    +  {certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]}]).
    +  {ok,{sslsocket,[...]}}

    Step 6: Upgrade to a TLS connection. The client and server must agree upon the upgrade. The server must be prepared to be a TLS server before the client can do -a successful connect.

    3 client>{ok, TLSSocket} = ssl:connect(Socket, [{verify, verify_peer},
    -  {cacertfile, "cacerts.pem"},
    -  {certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]}], infinity).
    -{ok,{sslsocket,[...]}}

    Step 7: Send a message over TLS:

    4 client> ssl:send(TLSSocket, "foo").
    -      ok

    Step 8: Set active once on the TLS socket:

    5 server> ssl:setopts(TLSSocket, [{active, once}]).
    +a successful connect.

    3 client>{ok, TLSSocket} = ssl:connect(Socket, [{verify, verify_peer},
    +  {cacertfile, "cacerts.pem"},
    +  {certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]}], infinity).
    +{ok,{sslsocket,[...]}}

    Step 7: Send a message over TLS:

    4 client> ssl:send(TLSSocket, "foo").
    +      ok

    Step 8: Set active once on the TLS socket:

    5 server> ssl:setopts(TLSSocket, [{active, once}]).
           ok

    Step 9: Flush the shell message queue to see that the message sent on the -client side is recived by the server side:

    5 server> flush().
    -      Shell got {ssl,{sslsocket,[...]},"foo"}
    +client side is recived by the server side:

    5 server> flush().
    +      Shell got {ssl,{sslsocket,[...]},"foo"}
           ok

    Customizing cipher suites

    Fetch default cipher suite list for a TLS/DTLS version. Change default to all to -get all possible cipher suites.

    1>  Default = ssl:cipher_suites(default, 'tlsv1.2').
    -    [#{cipher => aes_256_gcm,key_exchange => ecdhe_ecdsa,
    -    mac => aead,prf => sha384}, ....]

    In OTP 20 it is desirable to remove all cipher suites that uses rsa key exchange +get all possible cipher suites.

    1>  Default = ssl:cipher_suites(default, 'tlsv1.2').
    +    [#{cipher => aes_256_gcm,key_exchange => ecdhe_ecdsa,
    +    mac => aead,prf => sha384}, ....]

    In OTP 20 it is desirable to remove all cipher suites that uses rsa key exchange (removed from default in 21)

    2> NoRSA =
    -    ssl:filter_cipher_suites(Default,
    -                             [{key_exchange, fun(rsa) -> false;
    -                                                (_) -> true
    -                                             end}]).
    -    [...]

    Pick just a few suites

     3> Suites =
    - ssl:filter_cipher_suites(Default,
    -                             [{key_exchange, fun(ecdh_ecdsa) -> true;
    -                                                (_) -> false
    -                                             end},
    -                              {cipher, fun(aes_128_cbc) -> true;
    -                                          (_) ->false
    -                                       end}]).
    -
    -[#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
    -   mac => sha256,prf => sha256},
    - #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
    -   prf => default_prf}]

    Make some particular suites the most preferred, or least preferred by changing -prepend to append.

     4>ssl:prepend_cipher_suites(Suites, Default).
    -  [#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
    -     mac => sha256,prf => sha256},
    -   #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
    -     prf => default_prf},
    -   #{cipher => aes_256_cbc,key_exchange => ecdhe_ecdsa,
    -     mac => sha384,prf => sha384}, ...]

    Customizing signature algorithms(TLS-1.2)/schemes(TLS-1.3)

    Starting from TLS-1.2 signature algorithms (called signature schemes in TLS-1.3) + ssl:filter_cipher_suites(Default, + [{key_exchange, fun(rsa) -> false; + (_) -> true + end}]). + [...]

    Pick just a few suites

     3> Suites =
    + ssl:filter_cipher_suites(Default,
    +                             [{key_exchange, fun(ecdh_ecdsa) -> true;
    +                                                (_) -> false
    +                                             end},
    +                              {cipher, fun(aes_128_cbc) -> true;
    +                                          (_) ->false
    +                                       end}]).
    +
    +[#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
    +   mac => sha256,prf => sha256},
    + #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
    +   prf => default_prf}]

    Make some particular suites the most preferred, or least preferred by changing +prepend to append.

     4>ssl:prepend_cipher_suites(Suites, Default).
    +  [#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
    +     mac => sha256,prf => sha256},
    +   #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
    +     prf => default_prf},
    +   #{cipher => aes_256_cbc,key_exchange => ecdhe_ecdsa,
    +     mac => sha384,prf => sha384}, ...]

    Customizing signature algorithms(TLS-1.2)/schemes(TLS-1.3)

    Starting from TLS-1.2 signature algorithms (called signature schemes in TLS-1.3) is something that can be negotiated and hence also configured. These algorithms/schemes will be used for digital signatures in protocol messages and in certificates.

    Note

    TLS-1.3 schemes have atom names whereas TLS-1.2 configuration is two element @@ -127,9 +127,9 @@ suite that is chosen, which is not the case in TLS-1.3.

    Using the function ssl:signature_algs/2 will let you inspect different aspects of possible configurations for your system. For example if TLS-1.3 and TLS-1.2 is supported the default signature_algorithm list in OTP-26 and cryptolib from -OpenSSL 3.0.2 would look like:

     1>  ssl:signature_algs(default, 'tlsv1.3').
    +OpenSSL 3.0.2 would look like:

     1>  ssl:signature_algs(default, 'tlsv1.3').
      %% TLS-1.3 schemes
    - [eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,
    + [eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,
       ecdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,
       rsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,
       rsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,
    @@ -137,47 +137,47 @@
       %% (would have a tuple name in TLS-1.2 only configuration)
       rsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256
       %% TLS 1.2 algorithms
    -  {sha512,ecdsa},
    -  {sha384,ecdsa},
    -  {sha256,ecdsa}]

    If you want to add support for non default supported algorithms you should + {sha512,ecdsa}, + {sha384,ecdsa}, + {sha256,ecdsa}]

    If you want to add support for non default supported algorithms you should append them to the default list as the configuration is in prefered order, -something like this:

        MySignatureAlgs = ssl:signature_algs(default, 'tlsv1.3') ++ [{sha, rsa}, {sha, dsa}],
    -    ssl:connect(Host,Port,[{signature_algs, MySignatureAlgs,...]}),
    +something like this:

        MySignatureAlgs = ssl:signature_algs(default, 'tlsv1.3') ++ [{sha, rsa}, {sha, dsa}],
    +    ssl:connect(Host,Port,[{signature_algs, MySignatureAlgs,...]}),
         ...

    See also ssl:signature_algs/2 and sign_algo()

    Using an Engine Stored Key

    Erlang ssl application is able to use private keys provided by OpenSSL engines -using the following mechanism:

    1> ssl:start().
    +using the following mechanism:

    1> ssl:start().
     ok

    Load a crypto engine, should be done once per engine used. For example -dynamically load the engine called MyEngine:

    2> {ok, EngineRef} =
    -crypto:engine_load(<<"dynamic">>,
    -[{<<"SO_PATH">>, "/tmp/user/engines/MyEngine"},<<"LOAD">>],
    -[]).
    -{ok,#Ref<0.2399045421.3028942852.173962>}

    Create a map with the engine information and the algorithm used by the engine:

    3> PrivKey =
    - #{algorithm => rsa,
    +dynamically load the engine called MyEngine:

    2> {ok, EngineRef} =
    +crypto:engine_load(<<"dynamic">>,
    +[{<<"SO_PATH">>, "/tmp/user/engines/MyEngine"},<<"LOAD">>],
    +[]).
    +{ok,#Ref<0.2399045421.3028942852.173962>}

    Create a map with the engine information and the algorithm used by the engine:

    3> PrivKey =
    + #{algorithm => rsa,
        engine => EngineRef,
    -   key_id => "id of the private key in Engine"}.

    Use the map in the ssl key option:

    4> {ok, SSLSocket} =
    - ssl:connect("localhost", 9999,
    /usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1026))
    --- old//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.html	2026-08-21 04:00:28.411353269 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl.html	2026-08-21 04:00:28.411353269 +0000
    @@ -96,9 +96,9 @@
     

    Interface functions for TLS (Transport Layer Security) and DTLS (Datagram Transport Layer Security).

    Note

    The application's name is still SSL because the first versions of the TLS protocol were named SSL (Secure Socket Layer). However, no version -of the old SSL protocol is supported by this application.

    Example:

    1> ssl:start(), ssl:connect("google.com", 443, [{verify, verify_peer},
    -    {cacerts, public_key:cacerts_get()}]).
    -{ok,{sslsocket, [...]}}

    See Examples for detailed usage and more examples of +of the old SSL protocol is supported by this application.

    Example:

    1> ssl:start(), ssl:connect("google.com", 443, [{verify, verify_peer},
    +    {cacerts, public_key:cacerts_get()}]).
    +{ok,{sslsocket, [...]}}

    See Examples for detailed usage and more examples of this API.

    Special Erlang node configuration for the application can be found in SSL Application.

    @@ -1979,26 +1979,26 @@ signature schemes supplied by the signature_algs_cert option.

    The TLS-1.2 default is Default_TLS_12_Alg_Pairs interleaved with rsa_pss_schemes since ssl-11.0 (Erlang/OTP 25). pss_pss is -preferred over pss_rsae, which in turn is preferred over rsa.

    The list for Default_TLS_12_Alg_Pairs is defined as follows:

    [
    -{sha512, ecdsa},
    -{sha512, rsa},
    -{sha384, ecdsa},
    -{sha384, rsa},
    -{sha256, ecdsa},
    -{sha256, rsa}
    -]

    Change

    • Support for {md5, rsa} was removed from the TLS-1.2 default in +preferred over pss_rsae, which in turn is preferred over rsa.

      The list for Default_TLS_12_Alg_Pairs is defined as follows:

      [
      +{sha512, ecdsa},
      +{sha512, rsa},
      +{sha384, ecdsa},
      +{sha384, rsa},
      +{sha256, ecdsa},
      +{sha256, rsa}
      +]

      Change

      • Support for {md5, rsa} was removed from the TLS-1.2 default in ssl-8.0 (Erlang/OTP 22).
      • Support for {sha, _} (SHA1) and {sha224, _} was removed -from the TLS-1.2 default in ssl-11.0 (Erlang/OTP 26).

      The list for rsa_pss_schemes is defined as follows:

      [rsa_pss_pss_sha512,
      +from the TLS-1.2 default in ssl-11.0 (Erlang/OTP 26).

    The list for rsa_pss_schemes is defined as follows:

    [rsa_pss_pss_sha512,
     rsa_pss_pss_sha384,
     rsa_pss_pss_sha256,
     rsa_pss_rsae_sha512,
     rsa_pss_rsae_sha384,
    -rsa_pss_rsae_sha256]

    The list of TLS_13_Legacy_Schemes is defined as follows:

    [
    +rsa_pss_rsae_sha256]

    The list of TLS_13_Legacy_Schemes is defined as follows:

    [
     %% Legacy algorithms only applicable to certificate signatures
     rsa_pkcs1_sha512, %% Corresponds to {sha512, rsa}
     rsa_pkcs1_sha384, %% Corresponds to {sha384, rsa}
     rsa_pkcs1_sha256, %% Corresponds to {sha256, rsa}
    -]

    The list of Default_TLS_13_Schemes is defined as follows:

    [
    +]

    The list of Default_TLS_13_Schemes is defined as follows:

    [
     %% EDDSA
     eddsa_ed25519,
     eddsa_ed448
    @@ -2317,8 +2317,8 @@
     
           
     
    -

    Claim an intermediate CA in the chain as trusted.

    fun(Chain::[public_key:der_encoded()]) ->
    -      {trusted_ca, DerCert::public_key:der_encoded()} | unknown_ca.

    TLS then uses public_key:pkix_path_validation/3 with the selected CA +

    Claim an intermediate CA in the chain as trusted.

    fun(Chain::[public_key:der_encoded()]) ->
    +      {trusted_ca, DerCert::public_key:der_encoded()} | unknown_ca.

    TLS then uses public_key:pkix_path_validation/3 with the selected CA as the trusted anchor and verifies the rest of the chain.

    @@ -2577,7 +2577,7 @@ being sent and disables the hostname verification check.

  • {customize_hostname_check, HostNameCheckOpts} - Customization option

    Customizes the hostname verification of the peer certificate, as various protocols that use TLS, such as HTTP or LDAP, may require different approaches. For example, here is how to use standard hostname checking for HTTPS implemented in -Public_Key:

    {customize_hostname_check, [{match_fun, public_key:pkix_verify_hostname_match_fun(https)}]}

    For futher description of the customize options, see +Public_Key:

    {customize_hostname_check, [{match_fun, public_key:pkix_verify_hostname_match_fun(https)}]}

    For futher description of the customize options, see public_key:pkix_verify_hostname/3.

  • {client_certificate_authorities, UseCertAuth} - Inter-op hint option

    If UseCertAuth is set to true, sends the certificate authorities extension in the TLS-1.3 client hello. The default is false. Note that setting UseCertAuth to true can result in a significant @@ -2593,21 +2593,21 @@ OCSP query or a CRL check. Note however that accepting {bad_cert, missing_ocsp_staple} without performing alternative revocation checking is insecure, as it allows a MITM attacker to -suppress revocation information by omitting the OCSP staple.

    {verify_fun, {fun(_, _, {bad_cert, missing_ocsp_staple} = R, _St) ->
    +suppress revocation information by omitting the OCSP staple.

    {verify_fun, {fun(_, _, {bad_cert, missing_ocsp_staple} = R, _St) ->
                           %% Implement fallback revocation check here,
                           %% e.g. a direct OCSP query or CRL check.
                           %% Simply returning {valid, St} skips
                           %% revocation checking entirely.
    -                      {fail, R};
    -                 (_, _, {bad_cert, _} = R, _) ->
    -                      {fail, R};
    -                 (_, _, {extension, _}, St) ->
    -                      {unknown, St};
    -                 (_, _, valid, St) ->
    -                      {valid, St};
    -                 (_, _, valid_peer, St) ->
    -                      {valid, St}
    -              end, []}}

    When Stapling is given as a map, boolean ocsp_nonce key can + {fail, R}; + (_, _, {bad_cert, _} = R, _) -> + {fail, R}; + (_, _, {extension, _}, St) -> + {unknown, St}; + (_, _, valid, St) -> + {valid, St}; + (_, _, valid_peer, St) -> + {valid, St} + end, []}}

    When Stapling is given as a map, boolean ocsp_nonce key can indicate whether an OCSP nonce should be requested by the client (default is false).

    Note

    The OCSP response can be provided without a nonce value — even if it was requested by the client. In such cases SSL will proceed with the handshake and generate @@ -2740,7 +2740,7 @@

    Options only relevant for TLS-1.3.

    • {session_tickets, SessionTickets} - Use of session tickets

      Configures the session ticket functionality. Allowed values are disabled, manual, and auto. If it is set to manual the client will send the ticket -information to user process in a 3-tuple:

      {ssl, session_ticket, `Ticket::`(`t:session_ticket/0`)}

      where Ticket is a map with information about the created TLS-1.3 session ticket. +information to user process in a 3-tuple:

      {ssl, session_ticket, `Ticket::`(`t:session_ticket/0`)}

      where Ticket is a map with information about the created TLS-1.3 session ticket. The only key that the user needs to consider is sni key to be able to provide it as a value in the use_ticket option list of possible tickets to use it to attempt session resumption to a server identified by the @@ -2753,7 +2753,7 @@ mandatory option in manual mode ({session_tickets, manual}).

      Note

      Session tickets are only sent to the user if option session_tickets is set to manual

      This option is supported by TLS-1.3. See also SSL User's Guide, Session Tickets and Session Resumption in TLS 1.3.

    • {early_data, EarlyData}

      Configures the early data to be sent by the client.

      To verify that the server has the intention to process the early -data, the following tuple is sent to the user process:

      {ssl, SslSocket, {early_data, Result}}

      where Result is either accepted or rejected.

      Warning

      It is the responsibility of the user to handle rejected EarlyData and to +data, the following tuple is sent to the user process:

      {ssl, SslSocket, {early_data, Result}}

      where Result is either accepted or rejected.

      Warning

      It is the responsibility of the user to handle rejected EarlyData and to resend when appropriate.

    • {middlebox_comp_mode, MiddleBoxMode}

      Configures the middlebox compatibility mode for a TLS-1.3 connection.

      A significant number of middleboxes misbehave when a TLS-1.3 connection is negotiated. Implementations can increase the chance of making connections through those middleboxes by adapting the TLS-1.3 @@ -2942,20 +2942,20 @@ peer certificate in a valid certification path. So, if depth is 0 the PEER must be signed by the trusted ROOT-CA directly; if 1 the path can be PEER, CA, ROOT-CA; if 2 the path can be PEER, CA, CA, ROOT-CA, and so on. The default -value is 10. Used to mitigate DoS attack possibilities.

    • {verify_fun, Verify} - Customize certificate path validation

      The verification fun is to be defined as follows:

      fun(OtpCert :: #href_anchor"ss">'OTPCertificate'{},
      -    Event, InitialUserState :: term()) ->
      -  {valid, UserState :: term()} |
      -  {fail, Reason :: term()} | {unknown, UserState :: term()}.
      -
      -fun(OtpCert :: #'OTPCertificate'{}, DerCert :: public_key:der_encoded(),
      -    Event, InitialUserState :: term()) ->
      -  {valid, UserState :: term()} |
      -  {fail, Reason :: term()} | {unknown, UserState :: term()}.
      +value is 10. Used to mitigate DoS attack possibilities.

    • {verify_fun, Verify} - Customize certificate path validation

      The verification fun is to be defined as follows:

      fun(OtpCert :: #href_anchor"ss">'OTPCertificate'{},
      +    Event, InitialUserState :: term()) ->
      +  {valid, UserState :: term()} |
      +  {fail, Reason :: term()} | {unknown, UserState :: term()}.
      +
      +fun(OtpCert :: #'OTPCertificate'{}, DerCert :: public_key:der_encoded(),
      +    Event, InitialUserState :: term()) ->
      +  {valid, UserState :: term()} |
      +  {fail, Reason :: term()} | {unknown, UserState :: term()}.
       
       Types:
      -      Event = {bad_cert, Reason :: atom() |
      -              {revoked, atom()}} |
      -      {extension, #'Extension'{}} |
      +      Event = {bad_cert, Reason :: atom() |
      +              {revoked, atom()}} |
      +      {extension, #'Extension'{}} |
                     valid |
                     valid_peer

      The verification fun is called during the X.509-path validation when an error occurs or an extension unknown to the SSL application is @@ -2972,25 +2972,25 @@ handshake does not terminate regardless of verification failures, and the connection is established.

    • If called with an extension unknown to the user application, the fun is to return {unknown, UserState}.

    Note that if the fun returns unknown for an extension marked as critical, -validation will fail.

    Default option verify_fun in verify_peer mode:

    {fun(_, _, {bad_cert, _} = Reason, _) ->
    -   {fail, Reason};
    -    (_, _, {extension, _}, UserState) ->
    -   {unknown, UserState};
    -    (_, _, valid, UserState) ->
    -   {valid, UserState};
    -    (_, _, valid_peer, UserState) ->
    -       {valid, UserState}
    - end, []}

    Default option verify_fun in mode verify_none:

     {fun(_, _, {bad_cert, _}, UserState) ->
    -   {valid, UserState};
    -    (_, _, {extension, #'Extension'{critical = true}}, UserState) ->
    -   {valid, UserState};
    -    (_, _, {extension, _}, UserState) ->
    -   {unknown, UserState};
    -    (_, _, valid, UserState) ->
    -   {valid, UserState};
    -    (_, _, valid_peer, UserState) ->
    -       {valid, UserState}
    - end, []}

    The possible path validation errors are given in the form {bad_cert, Reason}, +validation will fail.

    Default option verify_fun in verify_peer mode:

    {fun(_, _, {bad_cert, _} = Reason, _) ->
    +   {fail, Reason};
    +    (_, _, {extension, _}, UserState) ->
    +   {unknown, UserState};
    +    (_, _, valid, UserState) ->
    +   {valid, UserState};
    +    (_, _, valid_peer, UserState) ->
    +       {valid, UserState}
    + end, []}

    Default option verify_fun in mode verify_none:

     {fun(_, _, {bad_cert, _}, UserState) ->
    +   {valid, UserState};
    +    (_, _, {extension, #'Extension'{critical = true}}, UserState) ->
    +   {valid, UserState};
    +    (_, _, {extension, _}, UserState) ->
    +   {unknown, UserState};
    +    (_, _, valid, UserState) ->
    +   {valid, UserState};
    +    (_, _, valid_peer, UserState) ->
    +       {valid, UserState}
    + end, []}

    The possible path validation errors are given in the form {bad_cert, Reason}, where Reason is:

    • unknown_ca

      No trusted CA was found in the trusted store. The trusted /usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl_distribution.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1024)) --- old//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl_distribution.html 2026-08-21 04:00:28.437353438 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/ssl_distribution.html 2026-08-21 04:00:28.437353438 +0000 @@ -105,14 +105,14 @@ applications. Such a script is located in the bin directory of the Erlang distribution. The source for the script is found under the Erlang installation top directory under releases/<OTP version>/start_clean.rel.

      Do the following:

      • Copy that script to another location (and preferably another name).
      • Add the applications Crypto, Public Key, and SSL with their current version -numbers after the STDLIB application.

      The following shows an example .rel file with TLS added:

            {release, {"OTP  APN 181 01","R15A"}, {erts, "5.9"},
      -      [{kernel,"2.15"},
      -      {stdlib,"1.18"},
      -      {crypto, "2.0.3"},
      -      {public_key, "0.12"},
      -      {asn1, "4.0"},
      -      {ssl, "5.0"}
      -      ]}.

      The version numbers differ in your system. Whenever one of the applications +numbers after the STDLIB application.

    The following shows an example .rel file with TLS added:

          {release, {"OTP  APN 181 01","R15A"}, {erts, "5.9"},
    +      [{kernel,"2.15"},
    +      {stdlib,"1.18"},
    +      {crypto, "2.0.3"},
    +      {public_key, "0.12"},
    +      {asn1, "4.0"},
    +      {ssl, "5.0"}
    +      ]}.

    The version numbers differ in your system. Whenever one of the applications included in the script is upgraded, change the script.

    Do the following:

    • Build the boot script.

      Assuming the .rel file is stored in a file start_ssl.rel in the current directory, a boot script can be built as follows:

       1> systools:make_script("start_ssl",[]).

    There is now a start_ssl.boot file in the current directory.

    Do the following:

    • Test the boot script. To do this, start Erlang with the -boot command-line parameter specifying this boot script (with its full path, but without the @@ -147,10 +147,10 @@ so beware!

    For TLS to work, at least a public key and a certificate must be specified for the server side and the client needs to specify CAs that it trusts (client certification is optional and requires more configuration).

    In the following example (to keep it simple), the PEM file "/home/me/ssl/erlserver.pem" -contains both the server certificate and its private key .

    Create a file named for example "/home/me/ssl/ssl_test@myhost.conf":

    [{server,
    -  [{certfile, "/home/me/ssl/erlserver.pem"}]},
    - {client,
    -  [{cacertfile, "/home/me/ssl/client_trusted.pem"}]}].

    And then start the node like this (line breaks in the command are for +contains both the server certificate and its private key .

    Create a file named for example "/home/me/ssl/ssl_test@myhost.conf":

    [{server,
    +  [{certfile, "/home/me/ssl/erlserver.pem"}]},
    + {client,
    +  [{cacertfile, "/home/me/ssl/client_trusted.pem"}]}].

    And then start the node like this (line breaks in the command are for readability, and shall not be there when typed):

    $ erl -boot /home/me/ssl/start_ssl -proto_dist inet_tls
       -ssl_dist_optfile "/home/me/ssl/ssl_test@myhost.conf"
       -sname ssl_test

    The options in the {server, Opts} tuple are used when calling @@ -168,25 +168,25 @@ present any certificate.

    A node started in this way is fully functional, using TLS as the distribution protocol.

    verify_fun Configuration Example

    The verify_fun option creates a reference to the implementing function since the configuration is evaluated as an Erlang term. In -an example file for use with -ssl_dist_optfile:

    [{server,[{fail_if_no_peer_cert,true},
    -          {certfile,"/home/me/ssl/cert.pem"},
    -          {keyfile,"/home/me/ssl/privkey.pem"},
    -          {cacertfile,"/home/me/ssl/ca_cert.pem"},
    -          {verify,verify_peer},
    -          {verify_fun,{fun mydist:verify/3,"any initial value"}}]},
    - {client,[{certfile,"/home/me/ssl/cert.pem"},
    -          {keyfile,"/home/me/ssl/privkey.pem"},
    -          {cacertfile,"/home/me/ssl/ca_cert.pem"},
    -          {verify,verify_peer},
    -          {verify_fun,{fun mydist:verify/3,"any initial value"}}]}].
    -

    mydist:verify/3 will be called with:

    • OtpCert, the other party's certificate PKIX Certificates
    • SslStatus, OTP's verification outcome, such as valid or a tuple {bad_cert, unknown_ca}
    • Init will be "any initial value"

    A pattern for verify/3 will look like:

    verify(OtpCert, _SslStatus, Init) ->
    -    IsOk = is_ok(OtpCert, Init),
    +an example file for use with -ssl_dist_optfile:

    [{server,[{fail_if_no_peer_cert,true},
    +          {certfile,"/home/me/ssl/cert.pem"},
    +          {keyfile,"/home/me/ssl/privkey.pem"},
    +          {cacertfile,"/home/me/ssl/ca_cert.pem"},
    +          {verify,verify_peer},
    +          {verify_fun,{fun mydist:verify/3,"any initial value"}}]},
    + {client,[{certfile,"/home/me/ssl/cert.pem"},
    +          {keyfile,"/home/me/ssl/privkey.pem"},
    +          {cacertfile,"/home/me/ssl/ca_cert.pem"},
    +          {verify,verify_peer},
    +          {verify_fun,{fun mydist:verify/3,"any initial value"}}]}].
    +

    mydist:verify/3 will be called with:

    • OtpCert, the other party's certificate PKIX Certificates
    • SslStatus, OTP's verification outcome, such as valid or a tuple {bad_cert, unknown_ca}
    • Init will be "any initial value"

    A pattern for verify/3 will look like:

    verify(OtpCert, _SslStatus, Init) ->
    +    IsOk = is_ok(OtpCert, Init),
         NewInitValue = "some new value",
         case IsOk of
            true ->
    -           {valid, NewInitValue};
    +           {valid, NewInitValue};
            false ->
    -           {failure, NewInitValue}
    +           {failure, NewInitValue}
         end.

    verify_fun can accept a verify/4 function, which will receive:

    • OtpCert, the other party's certificate PKIX Certificates
    • DerCert, the other party's original DER Encoded certificate
    • SslStatus, OTP's verification outcome, such as valid or a tuple {bad_cert, unknown_ca}
    • Init will be "any initial value"

    The verify/4 can use the DerCert for atypical workarounds such as handling decoding errors and directly verifying signatures.

    For more details see {verify_fun, Verify} in common_option_cert

    Note

    The legacy command line format for verify_fun cannot be used in a -ssl_dist_optfile file as described below in @@ -226,19 +226,19 @@ -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] +Erlang (BEAM) emulator version 5.0 [source] -Eshell V5.0 (abort with ^G) -(ssl_test@myhost)1> init:get_arguments(). -[{root,["/usr/local/erlang"]}, - {progname,["erl "]}, - {sname,["ssl_test"]}, - {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"] - {home,["/home/me"]}]

    The init:get_arguments() call verifies that the correct arguments are supplied +Eshell V5.0 (abort with ^G) +(ssl_test@myhost)1> init:get_arguments(). +[{root,["/usr/local/erlang"]}, + {progname,["erl "]}, + {sname,["ssl_test"]}, + {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"] + {home,["/home/me"]}]

  • The init:get_arguments() call verifies that the correct arguments are supplied to the emulator.

    /usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/using_ssl.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2124)) --- old//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/using_ssl.html 2026-08-21 04:00:28.469353647 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/ssl-11.6.0.4/doc/html/using_ssl.html 2026-08-21 04:00:28.469353647 +0000 @@ -107,87 +107,87 @@ except for the purpose of pattern matching.

    Note

    Note that client certificate verification is optional for the server and needs additional conguration on both sides to work. The Certificate and keys, in the examples, are provided using the ssl:cert_key_conf/0 supplied in the certs_keys -introduced in OTP 25.

    Basic Client

     1 > ssl:start(), ssl:connect("google.com", 443, [{verify, verify_peer},
    -                                                 {cacerts, public_key:cacerts_get()}]).
    -   {ok,{sslsocket, [...]}}

    Basic Connection

    Step 1: Start the server side:

    1 server> ssl:start().
    +introduced in OTP 25.

    Basic Client

     1 > ssl:start(), ssl:connect("google.com", 443, [{verify, verify_peer},
    +                                                 {cacerts, public_key:cacerts_get()}]).
    +   {ok,{sslsocket, [...]}}

    Basic Connection

    Step 1: Start the server side:

    1 server> ssl:start().
     ok

    Step 2: with alternative certificates, in this example the EDDSA certificate will be preferred if TLS-1.3 is negotiated and the RSA certificate will always -be used for TLS-1.2 as it does not support the EDDSA algorithm:

    2 server> {ok, ListenSocket} =
    -ssl:listen(9999, [{certs_keys, [#{certfile => "eddsacert.pem",
    -                                  keyfile => "eddsakey.pem"},
    -                                #{certfile => "rsacert.pem",
    +be used for TLS-1.2 as it does not support the EDDSA algorithm:

    2 server> {ok, ListenSocket} =
    +ssl:listen(9999, [{certs_keys, [#{certfile => "eddsacert.pem",
    +                                  keyfile => "eddsakey.pem"},
    +                                #{certfile => "rsacert.pem",
                                       keyfile => "rsakey.pem",
    -                                  password => "foobar"}
    -                               ]},{reuseaddr, true}]).
    -{ok,{sslsocket, [...]}}

    Step 3: Do a transport accept on the TLS listen socket:

    3 server> {ok, TLSTransportSocket} = ssl:transport_accept(ListenSocket).
    -{ok,{sslsocket, [...]}}

    Note

    ssl:transport_accept/1 and ssl:handshake/2 are separate functions so that the + password => "foobar"} + ]},{reuseaddr, true}]). +{ok,{sslsocket, [...]}}

    Step 3: Do a transport accept on the TLS listen socket:

    3 server> {ok, TLSTransportSocket} = ssl:transport_accept(ListenSocket).
    +{ok,{sslsocket, [...]}}

    Note

    ssl:transport_accept/1 and ssl:handshake/2 are separate functions so that the handshake part can be called in a new Erlang process dedicated to handling the -connection

    Step 4: Start the client side:

    1 client> ssl:start().
    +connection

    Step 4: Start the client side:

    1 client> ssl:start().
     ok

    Be sure to configure trusted certificates to use for server certificate -verification.

    2 client> {ok, Socket} = ssl:connect("localhost", 9999,
    -      [{verify, verify_peer},
    -      {cacertfile, "cacerts.pem"}, {active, once}], infinity).
    -{ok,{sslsocket, [...]}}

    Step 5: Do the TLS handshake:

    4 server> {ok, Socket} = ssl:handshake(TLSTransportSocket).
    -{ok,{sslsocket, [...]}}

    Note

    A real server should use ssl:handshake/2, which accepts a timeout, to avoid DoS -attacks. In the example the timeout defaults to infinity.

    Step 6: Send a message over TLS:

    5 server> ssl:send(Socket, "foo").
    +verification.

    2 client> {ok, Socket} = ssl:connect("localhost", 9999,
    +      [{verify, verify_peer},
    +      {cacertfile, "cacerts.pem"}, {active, once}], infinity).
    +{ok,{sslsocket, [...]}}

    Step 5: Do the TLS handshake:

    4 server> {ok, Socket} = ssl:handshake(TLSTransportSocket).
    +{ok,{sslsocket, [...]}}

    Note

    A real server should use ssl:handshake/2, which accepts a timeout, to avoid DoS +attacks. In the example the timeout defaults to infinity.

    Step 6: Send a message over TLS:

    5 server> ssl:send(Socket, "foo").
     ok

    Step 7: Flush the shell message queue to see that the message sent on the -server side is recived by the client side:

    3 client> flush().
    -Shell got {ssl,{sslsocket,[...]},"foo"}
    +server side is recived by the client side:

    3 client> flush().
    +Shell got {ssl,{sslsocket,[...]},"foo"}
     ok

    Upgrade Example - TLS only

    Upgrading a a TCP/IP connection to a TLS connections is mostly used when there is a desire have unencrypted communication first and then later secure the communication channel by using TLS. Note that the client and server need to agree to do the upgrade in the protocol doing the communication. This is concept is often referenced as STARTLS and used in many protocols such as SMTP, -FTPS and HTTPS via a proxy.

    Warning

    Maximum security recommendations are however moving away from such solutions.

    To upgrade to a TLS connection:

    Step 1: Start the server side:

    1 server> ssl:start().
    +FTPS and HTTPS via a proxy.

    Warning

    Maximum security recommendations are however moving away from such solutions.

    To upgrade to a TLS connection:

    Step 1: Start the server side:

    1 server> ssl:start().
       ok

    Step 2: Create a normal TCP listen socket and ensure active is set to false and not set to any active mode otherwise TLS handshake messages can be -delivered to the wrong process.

    2 server> {ok, ListenSocket} = gen_tcp:listen(9999, [{reuseaddr, true},
    -  {active, false}]).
    -  {ok, #Port<0.475>}

    Step 3: Accept client connection:

    3 server> {ok, Socket} = gen_tcp:accept(ListenSocket).
    -  {ok, #Port<0.476>}

    Step 4: Start the client side:

    1 client> ssl:start().
    -  ok
    2 client> {ok, Socket} = gen_tcp:connect("localhost", 9999,  [], infinity).

    Step 5: Do the TLS handshake:

    4 server> {ok, TLSSocket} = ssl:handshake(Socket, [{verify, verify_peer},
    -  {fail_if_no_peer_cert, true},
    -  {cacertfile, "cacerts.pem"},
    -  {certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]}]).
    -  {ok,{sslsocket,[...]}}

    Step 6: Upgrade to a TLS connection. The client and server must agree upon the +delivered to the wrong process.

    2 server> {ok, ListenSocket} = gen_tcp:listen(9999, [{reuseaddr, true},
    +  {active, false}]).
    +  {ok, #Port<0.475>}

    Step 3: Accept client connection:

    3 server> {ok, Socket} = gen_tcp:accept(ListenSocket).
    +  {ok, #Port<0.476>}

    Step 4: Start the client side:

    1 client> ssl:start().
    +  ok
    2 client> {ok, Socket} = gen_tcp:connect("localhost", 9999,  [], infinity).

    Step 5: Do the TLS handshake:

    4 server> {ok, TLSSocket} = ssl:handshake(Socket, [{verify, verify_peer},
    +  {fail_if_no_peer_cert, true},
    +  {cacertfile, "cacerts.pem"},
    +  {certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]}]).
    +  {ok,{sslsocket,[...]}}

    Step 6: Upgrade to a TLS connection. The client and server must agree upon the upgrade. The server must be prepared to be a TLS server before the client can do -a successful connect.

    3 client>{ok, TLSSocket} = ssl:connect(Socket, [{verify, verify_peer},
    -  {cacertfile, "cacerts.pem"},
    -  {certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]}], infinity).
    -{ok,{sslsocket,[...]}}

    Step 7: Send a message over TLS:

    4 client> ssl:send(TLSSocket, "foo").
    -      ok

    Step 8: Set active once on the TLS socket:

    5 server> ssl:setopts(TLSSocket, [{active, once}]).
    +a successful connect.

    3 client>{ok, TLSSocket} = ssl:connect(Socket, [{verify, verify_peer},
    +  {cacertfile, "cacerts.pem"},
    +  {certs_keys, [#{certfile => "cert.pem", keyfile => "key.pem"}]}], infinity).
    +{ok,{sslsocket,[...]}}

    Step 7: Send a message over TLS:

    4 client> ssl:send(TLSSocket, "foo").
    +      ok

    Step 8: Set active once on the TLS socket:

    5 server> ssl:setopts(TLSSocket, [{active, once}]).
           ok

    Step 9: Flush the shell message queue to see that the message sent on the -client side is recived by the server side:

    5 server> flush().
    -      Shell got {ssl,{sslsocket,[...]},"foo"}
    +client side is recived by the server side:

    5 server> flush().
    +      Shell got {ssl,{sslsocket,[...]},"foo"}
           ok

    Customizing cipher suites

    Fetch default cipher suite list for a TLS/DTLS version. Change default to all to -get all possible cipher suites.

    1>  Default = ssl:cipher_suites(default, 'tlsv1.2').
    -    [#{cipher => aes_256_gcm,key_exchange => ecdhe_ecdsa,
    -    mac => aead,prf => sha384}, ....]

    In OTP 20 it is desirable to remove all cipher suites that uses rsa key exchange +get all possible cipher suites.

    1>  Default = ssl:cipher_suites(default, 'tlsv1.2').
    +    [#{cipher => aes_256_gcm,key_exchange => ecdhe_ecdsa,
    +    mac => aead,prf => sha384}, ....]

    In OTP 20 it is desirable to remove all cipher suites that uses rsa key exchange (removed from default in 21)

    2> NoRSA =
    -    ssl:filter_cipher_suites(Default,
    -                             [{key_exchange, fun(rsa) -> false;
    -                                                (_) -> true
    -                                             end}]).
    -    [...]

    Pick just a few suites

     3> Suites =
    - ssl:filter_cipher_suites(Default,
    -                             [{key_exchange, fun(ecdh_ecdsa) -> true;
    -                                                (_) -> false
    -                                             end},
    -                              {cipher, fun(aes_128_cbc) -> true;
    -                                          (_) ->false
    -                                       end}]).
    -
    -[#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
    -   mac => sha256,prf => sha256},
    - #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
    -   prf => default_prf}]

    Make some particular suites the most preferred, or least preferred by changing -prepend to append.

     4>ssl:prepend_cipher_suites(Suites, Default).
    -  [#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
    -     mac => sha256,prf => sha256},
    -   #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
    -     prf => default_prf},
    -   #{cipher => aes_256_cbc,key_exchange => ecdhe_ecdsa,
    -     mac => sha384,prf => sha384}, ...]

    Customizing signature algorithms(TLS-1.2)/schemes(TLS-1.3)

    Starting from TLS-1.2 signature algorithms (called signature schemes in TLS-1.3) + ssl:filter_cipher_suites(Default, + [{key_exchange, fun(rsa) -> false; + (_) -> true + end}]). + [...]

    Pick just a few suites

     3> Suites =
    + ssl:filter_cipher_suites(Default,
    +                             [{key_exchange, fun(ecdh_ecdsa) -> true;
    +                                                (_) -> false
    +                                             end},
    +                              {cipher, fun(aes_128_cbc) -> true;
    +                                          (_) ->false
    +                                       end}]).
    +
    +[#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
    +   mac => sha256,prf => sha256},
    + #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
    +   prf => default_prf}]

    Make some particular suites the most preferred, or least preferred by changing +prepend to append.

     4>ssl:prepend_cipher_suites(Suites, Default).
    +  [#{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,
    +     mac => sha256,prf => sha256},
    +   #{cipher => aes_128_cbc,key_exchange => ecdh_ecdsa,mac => sha,
    +     prf => default_prf},
    +   #{cipher => aes_256_cbc,key_exchange => ecdhe_ecdsa,
    +     mac => sha384,prf => sha384}, ...]

    Customizing signature algorithms(TLS-1.2)/schemes(TLS-1.3)

    Starting from TLS-1.2 signature algorithms (called signature schemes in TLS-1.3) is something that can be negotiated and hence also configured. These algorithms/schemes will be used for digital signatures in protocol messages and in certificates.

    Note

    TLS-1.3 schemes have atom names whereas TLS-1.2 configuration is two element @@ -199,9 +199,9 @@ suite that is chosen, which is not the case in TLS-1.3.

    Using the function ssl:signature_algs/2 will let you inspect different aspects of possible configurations for your system. For example if TLS-1.3 and TLS-1.2 is supported the default signature_algorithm list in OTP-26 and cryptolib from -OpenSSL 3.0.2 would look like:

     1>  ssl:signature_algs(default, 'tlsv1.3').
    +OpenSSL 3.0.2 would look like:

     1>  ssl:signature_algs(default, 'tlsv1.3').
      %% TLS-1.3 schemes
    - [eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,
    + [eddsa_ed25519,eddsa_ed448,ecdsa_secp521r1_sha512,
       ecdsa_secp384r1_sha384,ecdsa_secp256r1_sha256,
       rsa_pss_pss_sha512,rsa_pss_pss_sha384,rsa_pss_pss_sha256,
       rsa_pss_rsae_sha512,rsa_pss_rsae_sha384,rsa_pss_rsae_sha256,
    @@ -209,47 +209,47 @@
       %% (would have a tuple name in TLS-1.2 only configuration)
       rsa_pkcs1_sha512,rsa_pkcs1_sha384,rsa_pkcs1_sha256
       %% TLS 1.2 algorithms
    -  {sha512,ecdsa},
    -  {sha384,ecdsa},
    -  {sha256,ecdsa}]

    If you want to add support for non default supported algorithms you should + {sha512,ecdsa}, + {sha384,ecdsa}, + {sha256,ecdsa}]

    If you want to add support for non default supported algorithms you should append them to the default list as the configuration is in prefered order, -something like this:

        MySignatureAlgs = ssl:signature_algs(default, 'tlsv1.3') ++ [{sha, rsa}, {sha, dsa}],
    -    ssl:connect(Host,Port,[{signature_algs, MySignatureAlgs,...]}),
    +something like this:

        MySignatureAlgs = ssl:signature_algs(default, 'tlsv1.3') ++ [{sha, rsa}, {sha, dsa}],
    +    ssl:connect(Host,Port,[{signature_algs, MySignatureAlgs,...]}),
         ...

    See also ssl:signature_algs/2 and sign_algo()

    Using an Engine Stored Key

    Erlang ssl application is able to use private keys provided by OpenSSL engines -using the following mechanism:

    1> ssl:start().
    +using the following mechanism:

    1> ssl:start().
     ok

    Load a crypto engine, should be done once per engine used. For example -dynamically load the engine called MyEngine:

    2> {ok, EngineRef} =
    -crypto:engine_load(<<"dynamic">>,
    -[{<<"SO_PATH">>, "/tmp/user/engines/MyEngine"},<<"LOAD">>],
    -[]).
    -{ok,#Ref<0.2399045421.3028942852.173962>}

    Create a map with the engine information and the algorithm used by the engine:

    3> PrivKey =
    - #{algorithm => rsa,
    +dynamically load the engine called MyEngine:

    2> {ok, EngineRef} =
    +crypto:engine_load(<<"dynamic">>,
    +[{<<"SO_PATH">>, "/tmp/user/engines/MyEngine"},<<"LOAD">>],
    +[]).
    +{ok,#Ref<0.2399045421.3028942852.173962>}

    Create a map with the engine information and the algorithm used by the engine:

    3> PrivKey =
    + #{algorithm => rsa,
        engine => EngineRef,
    -   key_id => "id of the private key in Engine"}.

    Use the map in the ssl key option:

    4> {ok, SSLSocket} =
    - ssl:connect("localhost", 9999,
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/argparse.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1338))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/argparse.html	2026-08-21 04:00:28.503353868 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/argparse.html	2026-08-21 04:00:28.503353868 +0000
    @@ -105,20 +105,20 @@
     errors when users give the program invalid arguments.

    Quick start

    argparse is designed to work with escript. The example below is a fully functioning Erlang program accepting two command line arguments and printing their product.

    #href_anchor"w">
    -main(Args) ->
    -    argparse:run(Args, cli(), #{progname => mul}).
    +main(Args) ->
    +    argparse:run(Args, cli(), #{progname => mul}).
     
    -cli() ->
    -    #{
    -        arguments => [
    -            #{name => left, type => integer},
    -            #{name => right, type => integer}
    -        ],
    +cli() ->
    +    #{
    +        arguments => [
    +            #{name => left, type => integer},
    +            #{name => right, type => integer}
    +        ],
             handler =>
    -            fun (#{left := Left, right := Right}) ->
    -                io:format("~b~n", [Left * Right])
    +            fun (#{left := Left, right := Right}) ->
    +                io:format("~b~n", [Left * Right])
                 end
    -    }.

    Running this script with no arguments results in an error, accompanied by the + }.

    Running this script with no arguments results in an error, accompanied by the usage information.

    The cli function defines a single command with embedded handler accepting a map. Keys of the map are argument names as defined by the argument field of the command, left and right in the example. Values are taken from the @@ -126,25 +126,25 @@ specification. Both arguments in the example above are required (and therefore defined as positional).

    Command hierarchy

    A command may contain nested commands, forming a hierarchy. Arguments defined at the upper level command are automatically added to all nested commands. Nested -commands example (assuming progname is nested):

    cli() ->
    -  #{
    +commands example (assuming progname is nested):

    cli() ->
    +  #{
         %% top level argument applicable to all commands
    -    arguments => [#{name => top}],
    -      commands => #{
    -        "first" => #{
    +    arguments => [#{name => top}],
    +      commands => #{
    +        "first" => #{
               %% argument applicable to "first" command and
               %%  all commands nested into "first"
    -          arguments => [#{name => mid}],
    -          commands => #{
    -            "second" => #{
    +          arguments => [#{name => mid}],
    +          commands => #{
    +            "second" => #{
                   %% argument only applicable for "second" command
    -              arguments => [#{name => bottom}],
    -              handler => fun (A) -> io:format("~p~n", [A]) end
    -          }
    -        }
    -      }
    -    }
    -  }.

    In the example above, a 3-level hierarchy is defined. First is the script itself + arguments => [#{name => bottom}], + handler => fun (A) -> io:format("~p~n", [A]) end + } + } + } + } + }.

    In the example above, a 3-level hierarchy is defined. First is the script itself (nested), accepting the only argument top. Since it has no associated handler, run/3 will not accept user input omitting nested command selection. For this example, user has to supply 5 arguments in the command line, two being @@ -156,14 +156,14 @@ on all operating systems). Both options and positional arguments have 1 or more associated values. See argument specification to find more details about supported combinations.

    In the user input, short options may be concatenated with their values. Long -options support values separated by =. Consider this definition:

    cli() ->
    -  #{
    -    arguments => [
    -      #{name => long, long => "-long"},
    -      #{name => short, short => $s}
    -    ],
    -    handler => fun (Args) -> io:format("~p~n", [Args]) end
    -  }.

    Running ./args --long=VALUE prints #{long => "VALUE"}, running +options support values separated by =. Consider this definition:

    cli() ->
    +  #{
    +    arguments => [
    +      #{name => long, long => "-long"},
    +      #{name => short, short => $s}
    +    ],
    +    handler => fun (Args) -> io:format("~p~n", [Args]) end
    +  }.

    Running ./args --long=VALUE prints #{long => "VALUE"}, running ./args -sVALUE prints #{short => "VALUE"}

    argparse supports boolean flags concatenation: it is possible to shorten -r -f -v to -rfv.

    Shortened option names are not supported: it is not possible to use --my-argum instead of --my-argument-name even when such option can be unambiguously @@ -594,111 +594,111 @@ which case resulting argument map will either contain the default value, or not have the key at all.

    • name - Sets the argument name in the parsed argument map. If help is not defined, name is also used to generate the default usage message.

    • short - Defines a short (single character) form of an optional argument.

      %% Define a command accepting argument named myarg, with short form $a:
      -1> Cmd = #{arguments => [#{name => myarg, short => $a}]}.
      +1> Cmd = #{arguments => [#{name => myarg, short => $a}]}.
       %% Parse command line "-a str":
      -2> {ok, ArgMap, _, _} = argparse:parse(["-a", "str"], Cmd), ArgMap.
      +2> {ok, ArgMap, _, _} = argparse:parse(["-a", "str"], Cmd), ArgMap.
       
      -#{myarg => "str"}
      +#{myarg => "str"}
       
       %% Option value can be concatenated with the switch: "-astr"
      -3> {ok, ArgMap, _, _} = argparse:parse(["-astr"], Cmd), ArgMap.
      +3> {ok, ArgMap, _, _} = argparse:parse(["-astr"], Cmd), ArgMap.
       
      -#{myarg => "str"}

      By default all options expect a single value following the option switch. The -only exception is an option of a boolean type.

    • long - Defines a long form of an optional argument.

      1> Cmd = #{arguments => [#{name => myarg, long => "name"}]}.
      +#{myarg => "str"}

      By default all options expect a single value following the option switch. The +only exception is an option of a boolean type.

    • long - Defines a long form of an optional argument.

      1> Cmd = #{arguments => [#{name => myarg, long => "name"}]}.
       %% Parse command line "-name Erlang":
      -2> {ok, ArgMap, _, _} = argparse:parse(["-name", "Erlang"], Cmd), ArgMap.
      +2> {ok, ArgMap, _, _} = argparse:parse(["-name", "Erlang"], Cmd), ArgMap.
       
      -#{myarg => "Erlang"}
      +#{myarg => "Erlang"}
       %% Or use "=" to separate the switch and the value:
      -3> {ok, ArgMap, _, _} = argparse:parse(["-name=Erlang"], Cmd), ArgMap.
      +3> {ok, ArgMap, _, _} = argparse:parse(["-name=Erlang"], Cmd), ArgMap.
       
      -#{myarg => "Erlang"}

      If neither short not long is defined, the argument is treated as +#{myarg => "Erlang"}

    If neither short not long is defined, the argument is treated as positional.

  • required - Forces the parser to expect the argument to be present in the command line. By default, all positional argument are required, and all options are not.

  • default - Specifies the default value to put in the parsed argument map -if the value is not supplied in the command line.

    1> argparse:parse([], #{arguments => [#{name => myarg, short => $m}]}).
    +if the value is not supplied in the command line.

    1> argparse:parse([], #{arguments => [#{name => myarg, short => $m}]}).
     
    -{ok,#{}, ...
    -2> argparse:parse([], #{arguments => [#{name => myarg, short => $m, default => "def"}]}).
    +{ok,#{}, ...
    +2> argparse:parse([], #{arguments => [#{name => myarg, short => $m, default => "def"}]}).
     
    -{ok,#{myarg => "def"}, ...
  • type - Defines type conversion and validation routine. The default is +{ok,#{myarg => "def"}, ...

  • type - Defines type conversion and validation routine. The default is string, assuming no conversion.

  • nargs - Defines the number of following arguments to consume from the command line. By default, the parser consumes the next argument and converts it into an Erlang term according to the specified type.

    • pos_integer/0 - Consume exactly this number of positional arguments, fail if there is not enough. Value in the argument map contains a list of exactly this length. Example, defining a positional argument expecting 3 -integer values:

      1> Cmd = #{arguments => [#{name => ints, type => integer, nargs => 3}]},
      -argparse:parse(["1", "2", "3"], Cmd).
      +integer values:

      1> Cmd = #{arguments => [#{name => ints, type => integer, nargs => 3}]},
      +argparse:parse(["1", "2", "3"], Cmd).
       
      -{ok, #{ints => [1, 2, 3]}, ...

      Another example defining an option accepted as -env and expecting two -string arguments:

      1> Cmd = #{arguments => [#{name => env, long => "env", nargs => 2}]},
      -argparse:parse(["-env", "key", "value"], Cmd).
      +{ok, #{ints => [1, 2, 3]}, ...

      Another example defining an option accepted as -env and expecting two +string arguments:

      1> Cmd = #{arguments => [#{name => env, long => "env", nargs => 2}]},
      +argparse:parse(["-env", "key", "value"], Cmd).
       
      -{ok, #{env => ["key", "value"]}, ...
    • list - Consume all following arguments until hitting the next option +{ok, #{env => ["key", "value"]}, ...

  • list - Consume all following arguments until hitting the next option (starting with an option prefix). May result in an empty list added to the -arguments map.

    1> Cmd = #{arguments => [
    -  #{name => nodes, long => "nodes", nargs => list},
    -  #{name => verbose, short => $v, type => boolean}
    -]},
    -argparse:parse(["-nodes", "one", "two", "-v"], Cmd).
    +arguments map.

    1> Cmd = #{arguments => [
    +  #{name => nodes, long => "nodes", nargs => list},
    +  #{name => verbose, short => $v, type => boolean}
    +]},
    +argparse:parse(["-nodes", "one", "two", "-v"], Cmd).
     
    -{ok, #{nodes => ["one", "two"], verbose => true}, ...
  • nonempty_list - Same as list, but expects at least one argument. +{ok, #{nodes => ["one", "two"], verbose => true}, ...

  • nonempty_list - Same as list, but expects at least one argument. Returns an error if the following command line argument is an option switch (starting with the prefix).

  • 'maybe' - Consumes the next argument from the command line, if it does not start with an option prefix. Otherwise, adds a default value to the -arguments map.

    1> Cmd = #{arguments => [
    -  #{name => level, short => $l, nargs => 'maybe', default => "error"},
    -  #{name => verbose, short => $v, type => boolean}
    -]},
    -argparse:parse(["-l", "info", "-v"], Cmd).
    +arguments map.

    1> Cmd = #{arguments => [
    +  #{name => level, short => $l, nargs => 'maybe', default => "error"},
    +  #{name => verbose, short => $v, type => boolean}
    +]},
    +argparse:parse(["-l", "info", "-v"], Cmd).
     
    -{ok,#{level => "info",verbose => true}, ...
    +{ok,#{level => "info",verbose => true}, ...
     
     %% When "info" is omitted, argument maps receives the default "error"
    -2> argparse:parse(["-l", "-v"], Cmd).
    +2> argparse:parse(["-l", "-v"], Cmd).
     
    -{ok,#{level => "error",verbose => true}, ...
  • {'maybe', term()} - Consumes the next argument from the command line, +{ok,#{level => "error",verbose => true}, ...

  • {'maybe', term()} - Consumes the next argument from the command line, /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/array.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2403)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/array.html 2026-08-21 04:00:28.532354057 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/array.html 2026-08-21 04:00:28.532354057 +0000 @@ -101,14 +101,14 @@ reset/2). If you need to differentiate between unset and set entries, ensure that the default value cannot be confused with the values of set entries.

    The array never shrinks automatically. If an index I has been used to set an entry successfully, all indices in the range [0,I] stay accessible unless the -array size is explicitly changed by calling resize/2.

    Examples:

    Create a fixed-size array with entries 0-9 set to undefined:

    A0 = array:new(10).
    -10 = array:size(A0).

    Create an extendible array and set entry 17 to true, causing the array to grow -automatically:

    A1 = array:set(17, true, array:new()).
    -18 = array:size(A1).

    Read back a stored value:

    true = array:get(17, A1).

    Accessing an unset entry returns default value:

    undefined = array:get(3, A1)

    Accessing an entry beyond the last set entry also returns the default value, if -the array does not have fixed size:

    undefined = array:get(18, A1).

    "Sparse" functions ignore default-valued entries:

    A2 = array:set(4, false, A1).
    -[{4, false}, {17, true}] = array:sparse_to_orddict(A2).

    An extendible array can be made fixed-size later:

    A3 = array:fix(A2).

    A fixed-size array does not grow automatically and does not allow accesses -beyond the last set entry:

    {'EXIT',{badarg,_}} = (catch array:set(18, true, A3)).
    -{'EXIT',{badarg,_}} = (catch array:get(18, A3)).
    +array size is explicitly changed by calling resize/2.

    Examples:

    Create a fixed-size array with entries 0-9 set to undefined:

    A0 = array:new(10).
    +10 = array:size(A0).

    Create an extendible array and set entry 17 to true, causing the array to grow +automatically:

    A1 = array:set(17, true, array:new()).
    +18 = array:size(A1).

    Read back a stored value:

    true = array:get(17, A1).

    Accessing an unset entry returns default value:

    undefined = array:get(3, A1)

    Accessing an entry beyond the last set entry also returns the default value, if +the array does not have fixed size:

    undefined = array:get(18, A1).

    "Sparse" functions ignore default-valued entries:

    A2 = array:set(4, false, A1).
    +[{4, false}, {17, true}] = array:sparse_to_orddict(A2).

    An extendible array can be made fixed-size later:

    A3 = array:fix(A2).

    A fixed-size array does not grow automatically and does not allow accesses +beyond the last set entry:

    {'EXIT',{badarg,_}} = (catch array:set(18, true, A3)).
    +{'EXIT',{badarg,_}} = (catch array:get(18, A3)).
    @@ -1149,7 +1149,7 @@ array size; this also implies {fixed, true}. If N is not a non-negative integer, the call fails with reason badarg.

  • fixed or {fixed, true} - Creates a fixed-size array. See also fix/1.

  • {fixed, false} - Creates an extendible (non-fixed-size) array.

  • {default, Value} - Sets the default value for the array to Value.

  • Options are processed in the order they occur in the list, that is, later options have higher precedence.

    The default value is used as the value of uninitialized entries, and cannot be -changed once the array has been created.

    Examples:

    array:new(100)

    creates a fixed-size array of size 100.

    array:new({default,0})

    creates an empty, extendible array whose default value is 0.

    array:new([{size,10},{fixed,false},{default,-1}])

    creates an extendible array with initial size 10 whose default value is -1.

    See also fix/1, from_list/2, get/2, new/0, new/2, set/3.

    +changed once the array has been created.

    Examples:

    array:new(100)

    creates a fixed-size array of size 100.

    array:new({default,0})

    creates an empty, extendible array whose default value is 0.

    array:new([{size,10},{fixed,false},{default,-1}])

    creates an extendible array with initial size 10 whose default value is -1.

    See also fix/1, from_list/2, get/2, new/0, new/2, set/3.

    @@ -1182,7 +1182,7 @@ Options override parameter Size.

    If Options is a list, this is equivalent to new([{size, Size} | Options]), otherwise it is equivalent to new([{size, Size} | [Options]]). However, using this function -directly is more efficient.

    Example:

    array:new(100, {default,0})

    creates a fixed-size array of size 100, whose default value is 0.

    See also new/1.

    +directly is more efficient.

    Example:

    array:new(100, {default,0})

    creates a fixed-size array of size 100, whose default value is 0.

    See also new/1.

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/assert_hrl.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1299)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/assert_hrl.html 2026-08-21 04:00:28.550354174 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/assert_hrl.html 2026-08-21 04:00:28.550354174 +0000 @@ -90,7 +90,7 @@

    Assert macros.

    Description

    The include file assert.hrl provides macros for inserting assertions in your -program code.

    Include the following directive in the module from which the function is called:

    -include_lib("stdlib/include/assert.hrl").

    When an assertion succeeds, the assert macro yields the atom ok. When an +program code.

    Include the following directive in the module from which the function is called:

    -include_lib("stdlib/include/assert.hrl").

    When an assertion succeeds, the assert macro yields the atom ok. When an assertion fails, an exception of type error is generated. The associated error term has the form {Macro, Info}. Macro is the macro name, for example, assertEqual. Info is a list of tagged values, such as @@ -112,7 +112,7 @@ use ASSERT/NOASSERT to control only the assert macros.

    Macros

    • assert(BoolExpr)

    • assert(BoolExpr, Comment) - Tests that BoolExpr completes normally returning true.

    • assertNot(BoolExpr)

    • assertNot(BoolExpr, Comment) - Tests that BoolExpr completes normally returning false.

    • assertMatch(GuardedPattern, Expr)

    • assertMatch(GuardedPattern, Expr, Comment) - Tests that Expr completes -normally yielding a value that matches GuardedPattern, for example:

      ?assertMatch({bork, _}, f())

      Notice that a guard when ... can be included:

      ?assertMatch({bork, X} when X > 0, f())
    • assertNotMatch(GuardedPattern, Expr)

    • assertNotMatch(GuardedPattern, Expr, Comment) - Tests that Expr +normally yielding a value that matches GuardedPattern, for example:

      ?assertMatch({bork, _}, f())

      Notice that a guard when ... can be included:

      ?assertMatch({bork, X} when X > 0, f())
    • assertNotMatch(GuardedPattern, Expr)

    • assertNotMatch(GuardedPattern, Expr, Comment) - Tests that Expr completes normally yielding a value that does not match GuardedPattern.

      As in assertMatch, GuardedPattern can have a when part.

    • assertEqual(ExpectedValue, Expr)

    • assertEqual(ExpectedValue, Expr, Comment) - Tests that Expr completes normally yielding a value that is exactly equal to ExpectedValue.

    • assertNotEqual(ExpectedValue, Expr)

    • assertNotEqual(ExpectedValue, Expr, Comment) - Tests that Expr completes normally yielding a value that is not exactly equal to /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/base64.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/base64.html 2026-08-21 04:00:28.574354330 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/base64.html 2026-08-21 04:00:28.574354330 +0000 @@ -636,16 +636,16 @@

      Decodes a base64 string encoded using the standard alphabet according to RFC 4648 Section 4 to plain ASCII.

      The function will strip away any whitespace characters and check for the -the correct number of = padding characters at the end of the encoded string.

      See decode_options/0 for details on which options can be passed.

      Example:

      1> base64:decode("AQIDBA==").
      -<<1,2,3,4>>
      -2> base64:decode("AQ ID BA==").
      -<<1,2,3,4>>
      -3> base64:decode("AQIDBA=").
      +the correct number of = padding characters at the end of the encoded string.

      See decode_options/0 for details on which options can be passed.

      Example:

      1> base64:decode("AQIDBA==").
      +<<1,2,3,4>>
      +2> base64:decode("AQ ID BA==").
      +<<1,2,3,4>>
      +3> base64:decode("AQIDBA=").
       ** exception error: missing_padding
            in function  base64:decode_list/7 (base64.erl, line 734)
               *** data to decode is missing final = padding characters, if this is intended, use the `padding => false` option
      -4> base64:decode("AQIDBA=", #{ padding => false }).
      -<<1,2,3,4>>
      +4>
      base64:decode("AQIDBA=", #{ padding => false }). +<<1,2,3,4>>
    @@ -899,10 +899,10 @@

    Decodes a base64 "mime" string encoded using the standard alphabet according to RFC 4648 Section 4 to plain ASCII.

    The function will strip away any illegal characters. It does not check for the -the correct number of = padding characters at the end of the encoded string.

    See decode_options/0 for details on which options can be passed.

    Example:

    1> base64:mime_decode("AQIDBA==").
    -<<1,2,3,4>>
    -2> base64:mime_decode("AQIDB=A=").
    -<<1,2,3,4>>
    +the correct number of = padding characters at the end of the encoded string.

    See decode_options/0 for details on which options can be passed.

    Example:

    1> base64:mime_decode("AQIDBA==").
    +<<1,2,3,4>>
    +2> base64:mime_decode("AQIDB=A=").
    +<<1,2,3,4>>
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/beam_lib.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1372)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/beam_lib.html 2026-08-21 04:00:28.617354610 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/beam_lib.html 2026-08-21 04:00:28.608354551 +0000 @@ -104,8 +104,8 @@ Tools such as Debugger and Xref require the debug information to be included.

    Warning

    Source code can be reconstructed from the debug information. To prevent this, use encrypted debug information (see below).

    The debug information can also be removed from BEAM files using strip/1, strip_files/1, and/or strip_release/1.

    Reconstruct Source Code

    The following example shows how to reconstruct Erlang source code from the debug -information in a BEAM file Beam:

    {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(Beam,[abstract_code]).
    -io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).

    Encrypted Debug Information

    The debug information can be encrypted to keep the source code secret, but still +information in a BEAM file Beam:

    {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(Beam,[abstract_code]).
    +io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).

    Encrypted Debug Information

    The debug information can be encrypted to keep the source code secret, but still be able to use tools such as Debugger or Xref.

    To use encrypted debug information, a key must be provided to the compiler and beam_lib. The key is specified as a string. It is recommended that the string contains at least 32 characters and that both upper and lower case letters as @@ -125,13 +125,13 @@ user's home directory and then filename:basedir(user_config, "erlang"). If the file is found and contains a key, beam_lib implicitly creates a crypto key fun -and registers it.

    File .erlang.crypt is to contain a single list of tuples:

    {debug_info, Mode, Module, Key}

    Mode is the type of crypto algorithm; currently, the only allowed value is +and registers it.

    File .erlang.crypt is to contain a single list of tuples:

    {debug_info, Mode, Module, Key}

    Mode is the type of crypto algorithm; currently, the only allowed value is des3_cbc. Module is either an atom, in which case Key is only used for the module Module, or [], in which case Key is used for all modules. Key is the non-empty key string.

    Key in the first tuple where both Mode and Module match is used.

    The following is an example of an .erlang.crypt file that returns the same key -for all modules:

    [{debug_info, des3_cbc, [], "%>7}|pc/DM6Cga*68$Mw]L#&_Gejr]G^"}].

    The following is a slightly more complicated example of an .erlang.crypt -providing one key for module t and another key for all other modules:

    [{debug_info, des3_cbc, t, "My KEY"},
    - {debug_info, des3_cbc, [], "%>7}|pc/DM6Cga*68$Mw]L#&_Gejr]G^"}].

    Note

    Do not use any of the keys in these examples. Use your own keys.

    +for all modules:

    [{debug_info, des3_cbc, [], "%>7}|pc/DM6Cga*68$Mw]L#&_Gejr]G^"}].

    The following is a slightly more complicated example of an .erlang.crypt +providing one key for module t and another key for all other modules:

    [{debug_info, des3_cbc, t, "My KEY"},
    + {debug_info, des3_cbc, [], "%>7}|pc/DM6Cga*68$Mw]L#&_Gejr]G^"}].

    Note

    Do not use any of the keys in these examples. Use your own keys.

    @@ -1538,11 +1538,11 @@

    Registers an unary fun that is called if beam_lib must read an debug_info chunk that has been encrypted. The fun is held in a process that is started by the function.

    If a fun is already registered when attempting to register a fun, -{error, exists} is returned.

    The fun must handle the following arguments:

    CryptoKeyFun(init) -> ok | {ok, NewCryptoKeyFun} | {error, Term}

    Called when the fun is registered, in the process that holds the fun. Here the +{error, exists} is returned.

    The fun must handle the following arguments:

    CryptoKeyFun(init) -> ok | {ok, NewCryptoKeyFun} | {error, Term}

    Called when the fun is registered, in the process that holds the fun. Here the crypto key fun can do any necessary initializations. If {ok, NewCryptoKeyFun} is returned, NewCryptoKeyFun is registered instead of CryptoKeyFun. If {error, Term} is returned, the registration is aborted and -crypto_key_fun/1 also returns {error, Term}.

    CryptoKeyFun({debug_info, Mode, Module, Filename}) -> Key

    Called when the key is needed for module Module in the file named Filename. +crypto_key_fun/1 also returns {error, Term}.

    CryptoKeyFun({debug_info, Mode, Module, Filename}) -> Key

    Called when the key is needed for module Module in the file named Filename. Mode is the type of crypto algorithm; currently, the only possible value is des3_cbc. The call is to fail (raise an exception) if no key is available.

    CryptoKeyFun(clear) -> term()

    Called before the fun is unregistered. Here any cleaning up can be done. The return value is not important, but is passed back to the caller of @@ -1909,14 +1909,14 @@ -vsn(Vsn).

    If this attribute is not specified, the version defaults to the checksum of the module. Notice that if version Vsn is not a list, it is made into one, that is {ok,{Module,[Vsn]}} is returned. If there are many -vsn -module attributes, the result is the concatenated list of versions.

    Examples:

    1> beam_lib:version(a). % -vsn(1).
    -{ok,{a,[1]}}
    -2> beam_lib:version(b). % -vsn([1]).
    -{ok,{b,[1]}}
    -3> beam_lib:version(c). % -vsn([1]). -vsn(2).
    -{ok,{c,[1,2]}}
    -4> beam_lib:version(d). % no -vsn attribute
    -{ok,{d,[275613208176997377698094100858909383631]}}
    +module attributes, the result is the concatenated list of versions.

    Examples:

    1> beam_lib:version(a). % -vsn(1).
    +{ok,{a,[1]}}
    +2> beam_lib:version(b). % -vsn([1]).
    +{ok,{b,[1]}}
    +3> beam_lib:version(c). % -vsn([1]). -vsn(2).
    +{ok,{c,[1,2]}}
    +4> beam_lib:version(d). % no -vsn attribute
    +{ok,{d,[275613208176997377698094100858909383631]}}
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/binary.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (998)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/binary.html 2026-08-21 04:00:28.655354857 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/binary.html 2026-08-21 04:00:28.656354864 +0000 @@ -589,11 +589,11 @@

    Returns the byte at position Pos (zero-based) in binary Subject as an integer.

    If Pos >= byte_size(Subject), a badarg exception -is raised.

    Examples

    1> binary:at(<<5,19,72,33>>, 0).
    +is raised.

    Examples

    1> binary:at(<<5,19,72,33>>, 0).
     5
    -2> binary:at(<<5,19,72,33>>, 1).
    +2> binary:at(<<5,19,72,33>>, 1).
     19
    -3> binary:at(<<5,19,72,33>>, 4).
    +3> binary:at(<<5,19,72,33>>, 4).
     ** exception error: bad argument
          in function  binary:at/2
             called as binary:at(<<5,19,72,33>>,4)
    @@ -627,8 +627,8 @@

    Converts Subject to a list of byte()s, each -representing the value of one byte.

    Examples

    1> binary:bin_to_list(<<"erlang",0>>).
    -[101,114,108,97,110,103,0]
    +representing the value of one byte.

    Examples

    1> binary:bin_to_list(<<"erlang",0>>).
    +[101,114,108,97,110,103,0]
    @@ -690,10 +690,10 @@

    Converts part of Subject to a list of byte/0s, each representing -the value of one byte.

    Pos and Len denote which part of the Subject binary to convert.

    Examples

    1> binary:bin_to_list(<<"erlang">>, 1, 3).
    +the value of one byte.

    Pos and Len denote which part of the Subject binary to convert.

    Examples

    1> binary:bin_to_list(<<"erlang">>, 1, 3).
     "rla"
     %% or [114,108,97] in list notation.
    -2> binary:bin_to_list(<<"erlang">>, 5, 3).
    +2> binary:bin_to_list(<<"erlang">>, 5, 3).
     ** exception error: bad argument
          in function  binary:bin_to_list/3
             called as binary:bin_to_list(<<"erlang">>,5,3)
    @@ -740,9 +740,9 @@
     binary is specified, the set has only one element. The order of alternatives in
     a pattern is not significant.

    The list of binaries used for search alternatives must be flat, proper, and non-empty.

    If Pattern is not a binary or a flat proper non-empty list of binaries with -length greater than 0, a badarg exception is raised.

    Examples

    1> Pat = binary:compile_pattern(~"rain").
    -2> binary:match(~"the rain in spain", Pat).
    -{4,4}
    +length greater than 0, a badarg exception is raised.

    Examples

    1> Pat = binary:compile_pattern(~"rain").
    +2> binary:match(~"the rain in spain", Pat).
    +{4,4}
    @@ -779,13 +779,13 @@ more binary data than needed. In general, sharing binary data is beneficial.

    Only in special cases — when small parts reference large binaries and the large binaries are no longer used in any process — can deliberate copying be -beneficial.

    Examples

    1> HugeBinary = <<0:100_000/unit:8>>.
    -2> byte_size(HugeBinary).
    +beneficial.

    Examples

    1> HugeBinary = <<0:100_000/unit:8>>.
    +2> byte_size(HugeBinary).
     100000
    -3> Part = binary:part(HugeBinary, 0, 5).
    -<<0,0,0,0,0>>
    -4> Copy = binary:copy(Part).
    -<<0,0,0,0,0>>
    +3>
    Part = binary:part(HugeBinary, 0, 5). +<<0,0,0,0,0>> +4> Copy = binary:copy(Part). +<<0,0,0,0,0>>
    @@ -815,8 +815,8 @@ -

    Creates a binary with the content of Subject duplicated N times.

    This function always creates a new binary, even when N is 1.

    Examples

    1> binary:copy(~"-", 10).
    -<<"----------">>
    +

    Creates a binary with the content of Subject duplicated N times.

    This function always creates a new binary, even when N is 1.

    Examples

    1> binary:copy(~"-", 10).
    +<<"----------">>
    @@ -847,9 +847,9 @@

    Decodes a hex-encoded binary into a binary.

    An exception is raised if the size of the binary is not evenly divisble by two, -or if the binary contains any characters that do not represent hex digits.

    Examples

    1> binary:decode_hex(<<"666f6f">>).
    -<<"foo">>
    -2> binary:decode_hex(<<"A">>).
    +or if the binary contains any characters that do not represent hex digits.

    Examples

    1> binary:decode_hex(<<"666f6f">>).
    +<<"foo">>
    +2> binary:decode_hex(<<"A">>).
     ** exception error: bad argument
          in function  binary:decode_hex/1
             called as binary:decode_hex(<<"A">>)
    @@ -918,15 +918,15 @@
           
     
     

    Converts the binary digit representation, in big endian or little endian, of a -positive integer in Subject to an Erlang integer/0.

    Examples

    1> binary:decode_unsigned(<<7>>).
    +positive integer in Subject to an Erlang integer/0.

    Examples

    1> binary:decode_unsigned(<<7>>).
     7
    -2> binary:decode_unsigned(<<1,0>>).
    +2> binary:decode_unsigned(<<1,0>>).
     256
    -3> binary:decode_unsigned(<<169,138,199>>).
    +3> binary:decode_unsigned(<<169,138,199>>).
     11111111
    -4> binary:decode_unsigned(<<169,138,199>>, big).
    +4> binary:decode_unsigned(<<169,138,199>>, big).
     11111111
    -5> binary:decode_unsigned(<<169,138,199>>, little).
    +5> binary:decode_unsigned(<<169,138,199>>, little).
     13077161
    @@ -989,12 +989,12 @@

    Encodes a binary into a hex-encoded binary using the specified case for the -hexadecimal digits "a" to "f".

    Examples

    1> binary:encode_hex(<<"foo">>, uppercase).
    -<<"666F6F">>
    -2> binary:encode_hex(<<"/">>, uppercase).
    -<<"2F">>
    -3> binary:encode_hex(<<"/">>, lowercase).
    -<<"2f">>
    +hexadecimal digits "a" to "f".

    Examples

    1> binary:encode_hex(<<"foo">>, uppercase).
    +<<"666F6F">>
    +2> binary:encode_hex(<<"/">>, uppercase).
    +<<"2F">>
    +3> binary:encode_hex(<<"/">>, lowercase).
    +<<"2f">>
    @@ -1057,18 +1057,18 @@

    Converts a non-negative integer into the smallest possible unsigned binary representation, using either big-endian or little-endian format.

    If Unsigned is not a non-negative integer, a badarg exception is -raised.

    Examples

    1> binary:encode_unsigned(0, big).
    -<<0>>
    -2> binary:encode_unsigned(255, big).
    -<<255>>
    -3> binary:encode_unsigned(256, big).
    -<<1,0>>
    -4> binary:encode_unsigned(256, little).
    -<<0,1>>
    -5> binary:encode_unsigned(11111111, big).
    -<<169,138,199>>
    -6> binary:encode_unsigned(11111111, little).
    -<<199,138,169>>
    +raised.

    Examples

    1> binary:encode_unsigned(0, big).
    +<<0>>
    +2> binary:encode_unsigned(255, big).
    +<<255>>
    +3> binary:encode_unsigned(256, big).
    +<<1,0>>
    +4> binary:encode_unsigned(256, little).
    +<<0,1>>
    +5> binary:encode_unsigned(11111111, big).
    +<<169,138,199>>
    +6> binary:encode_unsigned(11111111, little).
    +<<199,138,169>>
    @@ -1098,9 +1098,9 @@ -

    Returns the first byte of binary Subject as an integer.

    If the size of Subject is zero, a badarg exception is raised.

    Examples

    1> binary:first(<<42,99,100>>).
    +

    Returns the first byte of binary Subject as an integer.

    If the size of Subject is zero, a badarg exception is raised.

    Examples

    1> binary:first(<<42,99,100>>).
     42
    -2> binary:first(<<>>).
    +2> binary:first(<<>>).
     ** exception error: bad argument
          in function  binary:first/1
             called as binary:first(<<>>)
    @@ -1134,8 +1134,8 @@
     
           
     
    -

    Joins a list of binaries together by a specified Separator.

    Equivalent to iolist_to_binary(lists:join(Separator, Binaries)), but faster.

    Examples

    1> binary:join([<<"a">>, <<"b">>, <<"c">>], <<", ">>).
    -<<"a, b, c">>
    +

    Joins a list of binaries together by a specified Separator.

    Equivalent to iolist_to_binary(lists:join(Separator, Binaries)), but faster.

    Examples

    1> binary:join([<<"a">>, <<"b">>, <<"c">>], <<", ">>).
    +<<"a, b, c">>
    @@ -1165,9 +1165,9 @@ -

    Returns the last byte of binary Subject as an integer.

    If the size of Subject is zero, a badarg exception is raised.

    Examples

    1> binary:last(<<42,99,100>>).
    +

    Returns the last byte of binary Subject as an integer.

    If the size of Subject is zero, a badarg exception is raised.

    Examples

    1> binary:last(<<42,99,100>>).
     100
    -2> binary:last(<<>>).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/c.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/c.html	2026-08-21 04:00:28.688355072 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/c.html	2026-08-21 04:00:28.688355072 +0000
    @@ -1717,7 +1717,7 @@
           
     
     

    Compiles and then loads the code for a file on all nodes. Options defaults to -[]. Compilation is equivalent to:

    compile:file(File, Options ++ [report_errors, report_warnings])
    +[]. Compilation is equivalent to:

    compile:file(File, Options ++ [report_errors, report_warnings])
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/calendar.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/calendar.html 2026-08-21 04:00:28.725355313 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/calendar.html 2026-08-21 04:00:28.725355313 +0000 @@ -1903,13 +1903,13 @@

    Converts an RFC 3339 timestamp into system time. The data format of RFC 3339 timestamps is described by RFC 3339. Starting from OTP 25.1, the minutes part of the time zone is optional.

    Valid option:

    • {unit, Unit} - The time unit of the return value. The default is -second.
    1> calendar:rfc3339_to_system_time("2018-02-01T16:17:58+01:00").
    +second.
    1> calendar:rfc3339_to_system_time("2018-02-01T16:17:58+01:00").
     1517498278
    -2> calendar:rfc3339_to_system_time("2018-02-01 15:18:02.088Z",
    -   [{unit, nanosecond}]).
    +2> calendar:rfc3339_to_system_time("2018-02-01 15:18:02.088Z",
    +   [{unit, nanosecond}]).
     1517498282088000000
    -3> calendar:rfc3339_to_system_time(<<"2018-02-01 15:18:02.088Z">>,
    -   [{unit, nanosecond}]).
    +3> calendar:rfc3339_to_system_time(<<"2018-02-01 15:18:02.088Z">>,
    +   [{unit, nanosecond}]).
     1517498282088000000
    @@ -2081,20 +2081,20 @@ second digits is three, six, or nine depending on what time unit is chosen. For native three fractional digits are included. Notice that trailing zeros are not removed from the fraction.

  • {return, Return} - The desired encoding type for the output, -whether a string or a binary is desired. Defaults to string.

  • 1> calendar:system_time_to_rfc3339(erlang:system_time(second)).
    +whether a string or a binary is desired. Defaults to string.

    1> calendar:system_time_to_rfc3339(erlang:system_time(second)).
     "2018-04-23T14:56:28+02:00"
    -2> calendar:system_time_to_rfc3339(erlang:system_time(second),
    -   [{offset, "-02:00"}]).
    +2> calendar:system_time_to_rfc3339(erlang:system_time(second),
    +   [{offset, "-02:00"}]).
     "2018-04-23T10:56:52-02:00"
    -3> calendar:system_time_to_rfc3339(erlang:system_time(second),
    -   [{offset, -7200}]).
    +3> calendar:system_time_to_rfc3339(erlang:system_time(second),
    +   [{offset, -7200}]).
     "2018-04-23T10:57:05-02:00"
    -4> calendar:system_time_to_rfc3339(erlang:system_time(millisecond),
    -   [{unit, millisecond}, {time_designator, $\s}, {offset, "Z"}]).
    +4> calendar:system_time_to_rfc3339(erlang:system_time(millisecond),
    +   [{unit, millisecond}, {time_designator, $\s}, {offset, "Z"}]).
     "2018-04-23 12:57:20.482Z"
    -5> calendar:system_time_to_rfc3339(erlang:system_time(millisecond),
    -   [{unit, millisecond}, {time_designator, $\s}, {offset, "Z"}, {return, binary}]).
    -<<"2018-04-23 12:57:20.482Z">>
    +5>
    calendar:system_time_to_rfc3339(erlang:system_time(millisecond), + [{unit, millisecond}, {time_designator, $\s}, {offset, "Z"}, {return, binary}]). +<<"2018-04-23 12:57:20.482Z">>
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/custom_shell.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1276)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/custom_shell.html 2026-08-21 04:00:28.749355469 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/custom_shell.html 2026-08-21 04:00:28.750355476 +0000 @@ -104,20 +104,20 @@ started by default in -noshell mode, so we don't have to do anything special here. To start the custom shell we then call shell:start_interactive/1.

    #!/usr/bin/env escript
     %% pshell.es
    --export([start/0]).
    -main(_Args) ->
    -    shell:start_interactive({?MODULE, start, []}),
    -    timer:sleep(infinity). %% Make sure the escript does not exit
    +-export([start/0]).
    +main(_Args) ->
    +    shell:start_interactive({?MODULE, start, []}),
    +    timer:sleep(infinity). %% Make sure the escript does not exit
     
    --spec start() -> pid().
    -start() ->
    -    spawn(fun() ->
    -                  io:format(~"Starting process inspection shell~n"),
    -                  loop()
    -          end).
    +-spec start() -> pid().
    +start() ->
    +    spawn(fun() ->
    +                  io:format(~"Starting process inspection shell~n"),
    +                  loop()
    +          end).
     
    -loop() ->
    -    receive _M -> loop() end.

    If we run the above we will get this:

    $ ./pshell.es
    +loop() ->
    +    receive _M -> loop() end.

    If we run the above we will get this:

    $ ./pshell.es
     Erlang/OTP 28 [DEVELOPMENT] [erts-15.0.1] [source-b395339a02] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
     
     Starting process inspection shell
    @@ -128,32 +128,32 @@
     io:standard_io/0 as this shell will be line based. However, for a more complex
     shell it is better to send get_until I/O requests
     as commands read that way can span multiple lines. So we expand our loop/0 with
    -a io:get_line/1 and pass the results to our parser.

    loop() ->
    -    case io:get_line("> ") of
    +a io:get_line/1 and pass the results to our parser.

    loop() ->
    +    case io:get_line("> ") of
             eof -> ok;
    -        {error, Reason} -> exit(Reason);
    -        Data -> eval(string:trim(Data))
    +        {error, Reason} -> exit(Reason);
    +        Data -> eval(string:trim(Data))
         end,
    -    loop().
    +    loop().
     
    -eval("list") ->
    +eval("list") ->
         Format = " ~.10ts | ~.10ts | ~.10ts~n",
    -    io:format(Format,["Pid", "Name", "MsgQ Len"]),
    -    [begin
    -         [{registered_name,Name},{message_queue_len,Len}]
    -             = erlang:process_info(Pid, [registered_name, message_queue_len]),
    -         io:format(Format,[to_list(Pid), to_list(Name), to_list(Len)])
    -     end || Pid <- processes()];
    -eval(Unknown) ->
    -    io:format("Unknown command: '~ts'~n",[Unknown]).
    +    io:format(Format,["Pid", "Name", "MsgQ Len"]),
    +    [begin
    +         [{registered_name,Name},{message_queue_len,Len}]
    +             = erlang:process_info(Pid, [registered_name, message_queue_len]),
    +         io:format(Format,[to_list(Pid), to_list(Name), to_list(Len)])
    +     end || Pid <- processes()];
    +eval(Unknown) ->
    +    io:format("Unknown command: '~ts'~n",[Unknown]).
     
    -to_list(Pid) when is_pid(Pid) ->
    -    pid_to_list(Pid);
    -to_list(Atom) when is_atom(Atom) ->
    -    atom_to_list(Atom);
    -to_list(Int) when is_integer(Int) ->
    -    integer_to_list(Int);
    -to_list(List) when is_list(List) ->
    +to_list(Pid) when is_pid(Pid) ->
    +    pid_to_list(Pid);
    +to_list(Atom) when is_atom(Atom) ->
    +    atom_to_list(Atom);
    +to_list(Int) when is_integer(Int) ->
    +    integer_to_list(Int);
    +to_list(List) when is_list(List) ->
         List.

    If we run the above we will get this:

    $ ./pshell.es
     Erlang/OTP 28 [DEVELOPMENT] [erts-15.0.1] [source-b395339a02] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
     
    @@ -173,56 +173,56 @@
      <0.11.0>   | erl_prim_l | 0         
      <0.43.0>   | logger     | 0         
      <0.45.0>   | applicatio | 0
    -...

    With this all in place we can now easily add inspect, suspend and resume as well.

    eval("inspect " ++ PidStr) ->
    -    case parse_pid(PidStr) of
    +...

    With this all in place we can now easily add inspect, suspend and resume as well.

    eval("inspect " ++ PidStr) ->
    +    case parse_pid(PidStr) of
             invalid -> ok;
             Pid ->
    -            [{registered_name, Name}, {memory, Memory}, {messages, Messages}, {status, Status}] =
    -                erlang:process_info(Pid, [registered_name, memory, messages, status]),
    -            io:format("Pid: ~p~nName: ~ts~nStatus: ~p~nMemory: ~p~nMessages: ~p~n",
    -                      [Pid, to_list(Name), Status, Memory, Messages])
    +            [{registered_name, Name}, {memory, Memory}, {messages, Messages}, {status, Status}] =
    +                erlang:process_info(Pid, [registered_name, memory, messages, status]),
    +            io:format("Pid: ~p~nName: ~ts~nStatus: ~p~nMemory: ~p~nMessages: ~p~n",
    +                      [Pid, to_list(Name), Status, Memory, Messages])
         end;
    -eval("suspend " ++ PidStr) ->
    -    case parse_pid(PidStr) of
    +eval("suspend " ++ PidStr) ->
    +    case parse_pid(PidStr) of
             invalid -> ok;
             Pid ->
    -            erlang:suspend_process(Pid),
    -            io:format("Suspeneded ~ts~n")
    +            erlang:suspend_process(Pid),
    +            io:format("Suspeneded ~ts~n")
         end;
    -eval("resume " ++ PidStr) ->
    -    case parse_pid(PidStr) of
    +eval("resume " ++ PidStr) ->
    +    case parse_pid(PidStr) of
             invalid -> ok;
             Pid ->
    -            erlang:resumne_process(Pid),
    -            io:format("Resumed ~ts~n")
    +            erlang:resumne_process(Pid),
    +            io:format("Resumed ~ts~n")
         end;

    Adding autocompletion

    Wouldn't it be great if we could add some simple auto-completion for our shell? We can do that by setting a edlin_expand fun for our shell. This is done by calling io:setopts([{expand_fun, Fun}]). The fun that we provide is will receive the reversed current line from edlin and is expected to return possible expansions. Let's start by adding a simple fun to -expand our commands.

    -spec start() -> pid().
    -start() ->
    -    spawn(fun() ->
    -                  io:setopts([{expand_fun, fun expand_fun/1}]),
    -                  io:format(~"Starting process inspection shell~n"),
    -                  loop()
    -          end).
    +expand our commands.

    -spec start() -> pid().
    +start() ->
    +    spawn(fun() ->
    +                  io:setopts([{expand_fun, fun expand_fun/1}]),
    +                  io:format(~"Starting process inspection shell~n"),
    +                  loop()
    +          end).
     
    --spec expand_fun(ReverseLine :: string()) -> {yes, string(), list(string())} |
    -          {no, nil(), nil()}.
    -expand_fun("") -> %% If line is empty, we list all available commands
    -    {yes, "", ["list", "inspect", "suspend", "resume"]};
    -expand_fun(Curr) ->
    -    expand_fun(lists:reverse(Curr), ["list", "inspect", "suspend", "resume"]).
    +-spec expand_fun(ReverseLine :: string()) -> {yes, string(), list(string())} |
    +          {no, nil(), nil()}.
    +expand_fun("") -> %% If line is empty, we list all available commands
    +    {yes, "", ["list", "inspect", "suspend", "resume"]};
    +expand_fun(Curr) ->
    +    expand_fun(lists:reverse(Curr), ["list", "inspect", "suspend", "resume"]).
     
    -expand_fun(_Curr, []) ->
    -    {no, "", []};
    -expand_fun(Curr, [Cmd | T]) ->
    -    case lists:prefix(Curr, Cmd) of
    +expand_fun(_Curr, []) ->
    +    {no, "", []};
    +expand_fun(Curr, [Cmd | T]) ->
    +    case lists:prefix(Curr, Cmd) of
             true ->
                 %% If Curr is a prefix of Cmd we subtract Curr from Cmd to get the
                 %% characters we need to complete with.
    -            {yes, lists:reverse(lists:reverse(Cmd) -- lists:reverse(Curr)), []};
    +            {yes, lists:reverse(lists:reverse(Cmd) -- lists:reverse(Curr)), []};
             false ->
    -            expand_fun(Curr, T)
    +            expand_fun(Curr, T)
         end.

    With the above code we will get expansions of our commands if we hit <TAB> in the shell. Its possible to make very complex completion algorithms, for example the Erlang shell has completions based on the function specifications of your code. It is important though that /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/dets.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/dets.html 2026-08-21 04:00:28.788355723 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/dets.html 2026-08-21 04:00:28.788355723 +0000 @@ -1873,14 +1873,14 @@

    Returns a list of all objects with key Key stored in table Name, for -example:

    2> dets:open_file(abc, [{type, bag}]).
    -{ok,abc}
    -3> dets:insert(abc, {1,2,3}).
    +example:

    2> dets:open_file(abc, [{type, bag}]).
    +{ok,abc}
    +3> dets:insert(abc, {1,2,3}).
     ok
    -4> dets:insert(abc, {1,3,4}).
    +4> dets:insert(abc, {1,3,4}).
     ok
    -5> dets:lookup(abc, 1).
    -[{1,2,3},{1,3,4}]

    If the table type is set, the function returns either the empty list or a list +5> dets:lookup(abc, 1). +[{1,2,3},{1,3,4}]

    If the table type is set, the function returns either the empty list or a list with one object, as there cannot be more than one object with a given key. If the table type is bag or duplicate_bag, the function returns a list of arbitrary length.

    Notice that the order of objects returned is unspecified. In particular, the @@ -2737,11 +2737,11 @@ specification is specified explicitly. This is how to state match specifications that cannot easily be expressed within the syntax provided by qlc.

    The following example uses an explicit match specification to traverse the -table:

    1> dets:open_file(t, []),
    -ok = dets:insert(t, [{1,a},{2,b},{3,c},{4,d}]),
    -MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),
    -QH1 = dets:table(t, [{traverse, {select, MS}}]).

    An example with implicit match specification:

    2> QH2 = qlc:q([{Y} || {X,Y} <- dets:table(t), (X > 1) or (X < 5)]).

    The latter example is equivalent to the former, which can be verified using -function qlc:info/1:

    3> qlc:info(QH1) =:= qlc:info(QH2).
    +table:

    1> dets:open_file(t, []),
    +ok = dets:insert(t, [{1,a},{2,b},{3,c},{4,d}]),
    +MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),
    +QH1 = dets:table(t, [{traverse, {select, MS}}]).

    An example with implicit match specification:

    2> QH2 = qlc:q([{Y} || {X,Y} <- dets:table(t), (X > 1) or (X < 5)]).

    The latter example is equivalent to the former, which can be verified using +function qlc:info/1:

    3> qlc:info(QH1) =:= qlc:info(QH2).
     true

    qlc:info/1 returns information about a query handle. In this case identical information is returned for the two query handles.

    @@ -2815,7 +2815,7 @@

    Applies Fun to each object stored in table Name in some unspecified order. Different actions are taken depending on the return value of Fun. The following Fun return values are allowed:

    • continue - Continue to perform the traversal. For example, the following -function can be used to print the contents of a table:

      fun(X) -> io:format("~p~n", [X]), continue end.
    • {continue, Val} - Continue the traversal and accumulate Val. The +function can be used to print the contents of a table:

      fun(X) -> io:format("~p~n", [X]), continue end.
    • {continue, Val} - Continue the traversal and accumulate Val. The following function is supplied to collect all objects of a table in a list:

      fun(X) -> {continue, X} end.
    • {done, Value} - Terminate the traversal and return [Value | Acc].

    Any other value OtherValue returned by Fun terminates the traversal and is returned immediately.

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/dict.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1050)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/dict.html 2026-08-21 04:00:28.814355892 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/dict.html 2026-08-21 04:00:28.814355892 +0000 @@ -97,13 +97,13 @@ difference is that while this module considers two keys as different if they do not match (=:=), orddict considers two keys as different if and only if they do not compare equal (==).

    Notes

    Functions append and append_list are included so that keyed values can be -stored in a list accumulator, for example:

    > D0 = dict:new(),
    -  D1 = dict:store(files, [], D0),
    -  D2 = dict:append(files, f1, D1),
    -  D3 = dict:append(files, f2, D2),
    -  D4 = dict:append(files, f3, D3),
    -  dict:fetch(files, D4).
    -[f1,f2,f3]

    This saves the trouble of first fetching a keyed value, appending a new value to +stored in a list accumulator, for example:

    > D0 = dict:new(),
    +  D1 = dict:store(files, [], D0),
    +  D2 = dict:append(files, f1, D1),
    +  D3 = dict:append(files, f2, D2),
    +  D4 = dict:append(files, f3, D3),
    +  dict:fetch(files, D4).
    +[f1,f2,f3]

    This saves the trouble of first fetching a keyed value, appending a new value to the list of stored values, and storing the result.

    Function fetch is to be used if the key is known to be in the dictionary, otherwise function find.

    See Also

    gb_trees, orddict

    @@ -858,10 +858,10 @@ the Key-Value pairs from both dictionaries are included in the new dictionary. If a key occurs in both dictionaries, Fun is called with the key and both values to return a new value. merge can be defined as follows, but is -faster:

    merge(Fun, D1, D2) ->
    -    fold(fun (K, V1, D) ->
    -                 update(K, fun (V2) -> Fun(K, V1, V2) end, V1, D)
    -         end, D2, D1).
    +faster:

    merge(Fun, D1, D2) ->
    +    fold(fun (K, V1, D) ->
    +                 update(K, fun (V2) -> Fun(K, V1, V2) end, V1, D)
    +         end, D2, D1).
    @@ -1074,8 +1074,8 @@

    Updates a value in a dictionary by calling Fun on the value to get a new value. If Key is not present in the dictionary, Initial is stored as the -first value. For example, append/3 can be defined as:

    append(Key, Val, D) ->
    -    update(Key, fun (Old) -> Old ++ [Val] end, [Val], D).
    +first value. For example, append/3 can be defined as:

    append(Key, Val, D) ->
    +    update(Key, fun (Old) -> Old ++ [Val] end, [Val], D).
    @@ -1106,8 +1106,8 @@

    Adds Increment to the value associated with Key and stores this value. If Key is not present in the dictionary, Increment is stored as the first -value.

    This can be defined as follows, but is faster:

    update_counter(Key, Incr, D) ->
    -    update(Key, fun (Old) -> Old + Incr end, Incr, D).
    +value.

    This can be defined as follows, but is faster:

    update_counter(Key, Incr, D) ->
    +    update(Key, fun (Old) -> Old + Incr end, Incr, D).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/epp.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1018)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/epp.html 2026-08-21 04:00:28.841356068 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/epp.html 2026-08-21 04:00:28.841356068 +0000 @@ -99,7 +99,7 @@ expression coding\s*[:=]\s*([-a-zA-Z0-9])+ selects the encoding. If the matching string is not a valid encoding, it is ignored. The valid encodings are Latin-1 and UTF-8, where the case of the characters can be chosen freely.

    Examples:

    %% coding: utf-8
    %% For this file we have chosen encoding = Latin-1
    %% -*- coding: latin-1 -*-

    Error Information

    ErrorInfo is the standard ErrorInfo structure that is returned from all I/O -modules. The format is as follows:

    {ErrorLine, Module, ErrorDescriptor}

    A string describing the error is obtained with the following call:

    Module:format_error(ErrorDescriptor)

    See Also

    erl_parse

    +modules. The format is as follows:

    {ErrorLine, Module, ErrorDescriptor}

    A string describing the error is obtained with the following call:

    Module:format_error(ErrorDescriptor)

    See Also

    erl_parse

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_error.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1131)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_error.html 2026-08-21 04:00:28.863356211 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_error.html 2026-08-21 04:00:28.864356218 +0000 @@ -276,7 +276,7 @@

    A fun used to format function arguments for BIF and function calls. By default -the following fun will be used:

    fun(Term, I) -> io_lib:print(Term, I, 80, 30) end
    +the following fun will be used:

    fun(Term, I) -> io_lib:print(Term, I, 80, 30) end
    @@ -397,23 +397,23 @@ caused the error starting at 1.

  • general - An error that is not associated with any argument caused the error.

  • reason - If the Reason should be printed differently than the default way.

  • If the text returned includes new-lines, format_exception/4 will indent the -text correctly.

    Example:

    -module(my_error_module).
    --export([atom_to_string/1, format_error/2]).
    +text correctly.

    Example:

    -module(my_error_module).
    +-export([atom_to_string/1, format_error/2]).
     
    -atom_to_string(Arg) when is_atom(Arg) ->
    -  atom_to_list(Arg);
    -atom_to_string(Arg) ->
    -  erlang:error(badarg,[Arg],
    -               [{error_info,#{ module => ?MODULE,
    -                               cause => #{ 1 => "should be an atom" }}}]).
    -
    -format_error(Reason, [{_M,_F,_As,Info}|_]) ->
    -  ErrorInfo = proplists:get_value(error_info, Info, #{}),
    -  ErrorMap = maps:get(cause, ErrorInfo),
    -  ErrorMap#{ general => "optional general information",
    -             reason => io_lib:format("~p: ~p",[?MODULE, Reason]) }.
    1> c(my_error_module).
    -{ok,my_error_module}
    -2> my_error_module:atom_to_string(1).
    +atom_to_string(Arg) when is_atom(Arg) ->
    +  atom_to_list(Arg);
    +atom_to_string(Arg) ->
    +  erlang:error(badarg,[Arg],
    +               [{error_info,#{ module => ?MODULE,
    +                               cause => #{ 1 => "should be an atom" }}}]).
    +
    +format_error(Reason, [{_M,_F,_As,Info}|_]) ->
    +  ErrorInfo = proplists:get_value(error_info, Info, #{}),
    +  ErrorMap = maps:get(cause, ErrorInfo),
    +  ErrorMap#{ general => "optional general information",
    +             reason => io_lib:format("~p: ~p",[?MODULE, Reason]) }.
    1> c(my_error_module).
    +{ok,my_error_module}
    +2> my_error_module:atom_to_string(1).
     ** exception error: my_error_module: badarg
          in function  my_error_module:atom_to_string/1
             called as my_error_module:atom_to_string(1)
    @@ -501,18 +501,18 @@
     
     

    Format the error reason and stack back-trace caught using try ... catch in the same style as the shell formats them.

    Example:

    try
    -    do_something()
    +    do_something()
     catch
         C:R:Stk ->
    -        Message = erl_error:format_exception(C, R, Stk),
    -        io:format(LogFile, "~ts\n", [Message])
    +        Message = erl_error:format_exception(C, R, Stk),
    +        io:format(LogFile, "~ts\n", [Message])
     end

    If error_info is provided with the exception, format_exception will use that information to provide additional information about the exception.

    Example:

    try
    -  erlang:raise(badarg,[],[{error_info,#{}}])
    +  erlang:raise(badarg,[],[{error_info,#{}}])
     catch
         C:R:Stk ->
    -        Message = erl_error:format_exception(C, R, Stk),
    -        io:format(LogFile, "~ts\n", [Message])
    +        Message = erl_error:format_exception(C, R, Stk),
    +        io:format(LogFile, "~ts\n", [Message])
     end

    See erlang:error/3 for details on how to raise an exception with error_info included.

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_eval.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (924)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_eval.html 2026-08-21 04:00:28.889356381 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_eval.html 2026-08-21 04:00:28.889356381 +0000 @@ -100,13 +100,13 @@ LocalFunctionHandler can be used to define a function that is called when there is a call to a local function. The argument can have the following formats:

    • {value,Func} - This defines a local function handler that is called -with:

      Func(Name, Arguments)

      Name is the name of the local function (an atom) and Arguments is a list +with:

      Func(Name, Arguments)

      Name is the name of the local function (an atom) and Arguments is a list of the evaluated arguments. The function handler returns the value of the local function. In this case, the current bindings cannot be accessed. To signal an error, the function handler calls exit/1 with a -suitable exit value.

    • {eval,Func} - This defines a local function handler that is called with:

      Func(Name, Arguments, Bindings)

      Name is the name of the local function (an atom), Arguments is a list of +suitable exit value.

    • {eval,Func} - This defines a local function handler that is called with:

      Func(Name, Arguments, Bindings)

      Name is the name of the local function (an atom), Arguments is a list of the unevaluated arguments, and Bindings are the current variable bindings. -The function handler returns:

      {value,Value,NewBindings}

      Value is the value of the local function and NewBindings are the updated +The function handler returns:

      {value,Value,NewBindings}

      Value is the value of the local function and NewBindings are the updated variable bindings. In this case, the function handler must itself evaluate all the function arguments and manage the bindings. To signal an error, the function handler calls exit/1 with a suitable exit value.

    • none - There is no local function handler.

    Non-Local Function Handler

    The optional argument NonLocalFunctionHandler can be used to define a function @@ -114,7 +114,7 @@ expressions.

  • An operator Op/A is called (this is handled as a call to function erlang:Op/A).
  • Exceptions are calls to erlang:apply/2,3; neither of the function handlers are called for such calls. The argument can have the following formats:

    • {value,Func} - This defines a non-local function handler. The function -may be called with two arguments:

      Func(FuncSpec, Arguments)

      or three arguments:

      Func(Anno, FuncSpec, Arguments)

      Anno is the erl_anno:anno() of the node, FuncSpec +may be called with two arguments:

      Func(FuncSpec, Arguments)

      or three arguments:

      Func(Anno, FuncSpec, Arguments)

      Anno is the erl_anno:anno() of the node, FuncSpec is the name of the function of the form {Module,Function} or a fun, and Arguments is a list of the evaluated arguments. The function handler returns the value of the function. To signal an error, the function handler /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_lint.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1074)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_lint.html 2026-08-21 04:00:28.910356517 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_lint.html 2026-08-21 04:00:28.910356517 +0000 @@ -98,7 +98,7 @@ appropriate option, described below.

      The functions in this module are invoked automatically by the Erlang compiler. There is no reason to invoke these functions separately unless you have written your own Erlang compiler.

      Error Information

      ErrorInfo is the standard ErrorInfo structure that is returned from all I/O -modules. The format is as follows:

      {ErrorLine, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      See Also

      epp, erl_parse

      +modules. The format is as follows:

      {ErrorLine, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      See Also

      epp, erl_parse

      /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_parse.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1214)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_parse.html 2026-08-21 04:00:28.961356849 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_parse.html 2026-08-21 04:00:28.961356849 +0000 @@ -97,7 +97,7 @@ form of either forms (that is, top-level constructs), expressions, or terms.

      The Abstract Format is described in the ERTS User's Guide. Notice that a token list must end with the dot token to be acceptable to the parse functions (see the erl_scan) module.

      Error Information

      ErrorInfo is the standard ErrorInfo structure that is returned from all I/O modules. -The format is as follows:

      {ErrorLine, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      See Also

      erl_anno, erl_scan, io, section The Abstract Format +The format is as follows:

      {ErrorLine, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      See Also

      erl_anno, erl_scan, io, section The Abstract Format in the ERTS User's Guide.

      /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_scan.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1022)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_scan.html 2026-08-21 04:00:28.987357019 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_scan.html 2026-08-21 04:00:28.987357019 +0000 @@ -95,7 +95,7 @@

      The Erlang token scanner.

      This module contains functions for tokenizing (scanning) characters into Erlang tokens.

      Error Information

      ErrorInfo is the standard ErrorInfo structure that is returned from all I/O -modules. The format is as follows:

      {ErrorLocation, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      Notes

      The continuation of the first call to the re-entrant input functions must be +modules. The format is as follows:

      {ErrorLocation, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      Notes

      The continuation of the first call to the re-entrant input functions must be []. For a complete description of how the re-entrant input scheme works, see Armstrong, Virding and Williams: 'Concurrent Programming in Erlang', Chapter 13.

      See Also

      erl_anno, erl_parse, io

      /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_tar.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1320)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_tar.html 2026-08-21 04:00:29.016357207 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/erl_tar.html 2026-08-21 04:00:29.016357207 +0000 @@ -1238,14 +1238,14 @@ Notice that there is only an arity-2 read function, not an arity-1 function.

    • (position,{UserData,Position}) - Sets the position of UserData as defined for files in file:position/2

    Example:

    The following is a complete Fun parameter for reading and writing on files using the file module:

    ExampleFun =
    -   fun(write, {Fd,Data}) ->  file:write(Fd, Data);
    -      (position, {Fd,Pos}) -> file:position(Fd, Pos);
    -      (read2, {Fd,Size}) -> file:read(Fd, Size);
    -      (close, Fd) -> file:close(Fd)
    -   end

    Here Fd was specified to function init/3 as:

    {ok,Fd} = file:open(Name, ...).
    -{ok,TarDesc} = erl_tar:init(Fd, [write], ExampleFun),

    TarDesc is then used:

    erl_tar:add(TarDesc, SomeValueIwantToAdd, FileNameInTarFile),
    +   fun(write, {Fd,Data}) ->  file:write(Fd, Data);
    +      (position, {Fd,Pos}) -> file:position(Fd, Pos);
    +      (read2, {Fd,Size}) -> file:read(Fd, Size);
    +      (close, Fd) -> file:close(Fd)
    +   end

    Here Fd was specified to function init/3 as:

    {ok,Fd} = file:open(Name, ...).
    +{ok,TarDesc} = erl_tar:init(Fd, [write], ExampleFun),

    TarDesc is then used:

    erl_tar:add(TarDesc, SomeValueIwantToAdd, FileNameInTarFile),
     ...,
    -erl_tar:close(TarDesc)

    When the erl_tar core wants to, for example, write a piece of Data, it would +erl_tar:close(TarDesc)

    When the erl_tar core wants to, for example, write a piece of Data, it would call ExampleFun(write, {UserData,Data}).

    Note

    This example with the file module operations is not necessary to use directly, as that is what function open/2 in principle does.

    Warning

    The TarDescriptor term is not a file descriptor. You are advised not to rely on the specific contents of this term, as it can change in future Erlang/OTP /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/escript.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1684)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/escript.html 2026-08-21 04:00:29.041357370 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/escript.html 2026-08-21 04:00:29.041357370 +0000 @@ -487,67 +487,67 @@ number of schedulers with +S3. We also extract the different sections from the newly created script:

    > Source = "%% Demo\nmain(_Args) ->\n    io:format(\"~p\",[erlang:system_info(schedulers)]).\n".
     "%% Demo\nmain(_Args) ->\n    io:format(erlang:system_info(schedulers)).\n"
    -> io:format("~s\n", [Source]).
    +> io:format("~s\n", [Source]).
     %% Demo
    -main(_Args) ->
    -    io:format(erlang:system_info(schedulers)).
    +main(_Args) ->
    +    io:format(erlang:system_info(schedulers)).
     
     ok
    -> {ok, Bin} = escript:create(binary, [shebang, comment, {emu_args, "+S3"},
    -                                      {source, list_to_binary(Source)}]).
    -{ok,<<"#!/usr/bin/env escript\n%% This is an -*- erlang -*- file\n%%!+S3"...>>}
    -> file:write_file("demo.escript", Bin).
    +> {ok, Bin} = escript:create(binary, [shebang, comment, {emu_args, "+S3"},
    +                                      {source, list_to_binary(Source)}]).
    +{ok,<<"#!/usr/bin/env escript\n%% This is an -*- erlang -*- file\n%%!+S3"...>>}
    +> file:write_file("demo.escript", Bin).
     ok
    -> os:cmd("escript demo.escript").
    +> os:cmd("escript demo.escript").
     "3"
    -> escript:extract("demo.escript", []).
    -{ok,[{shebang,default}, {comment,default}, {emu_args,"+S3"},
    -     {source,<<"%% Demo\nmain(_Args) ->\n    io:format(erlang:system_info(schedu"...>>}]}

    An escript without header can be created as follows:

    > file:write_file("demo.erl",
    -                  ["%% demo.erl\n-module(demo).\n-export([main/1]).\n\n", Source]).
    -ok
    -> {ok, _, BeamCode} = compile:file("demo.erl", [binary, debug_info]).
    -{ok,demo,
    -    <<70,79,82,49,0,0,2,208,66,69,65,77,65,116,111,109,0,0,0,
    -      79,0,0,0,9,4,100,...>>}
    -> escript:create("demo.beam", [{beam, BeamCode}]).
    -ok
    -> escript:extract("demo.beam", []).
    -{ok,[{shebang,undefined}, {comment,undefined}, {emu_args,undefined},
    -     {beam,<<70,79,82,49,0,0,3,68,66,69,65,77,65,116,
    -             111,109,0,0,0,83,0,0,0,9,...>>}]}
    -> os:cmd("escript demo.beam").
    +> escript:extract("demo.escript", []).
    +{ok,[{shebang,default}, {comment,default}, {emu_args,"+S3"},
    +     {source,<<"%% Demo\nmain(_Args) ->\n    io:format(erlang:system_info(schedu"...>>}]}

    An escript without header can be created as follows:

    > file:write_file("demo.erl",
    +                  ["%% demo.erl\n-module(demo).\n-export([main/1]).\n\n", Source]).
    +ok
    +> {ok, _, BeamCode} = compile:file("demo.erl", [binary, debug_info]).
    +{ok,demo,
    +    <<70,79,82,49,0,0,2,208,66,69,65,77,65,116,111,109,0,0,0,
    +      79,0,0,0,9,4,100,...>>}
    +> escript:create("demo.beam", [{beam, BeamCode}]).
    +ok
    +> escript:extract("demo.beam", []).
    +{ok,[{shebang,undefined}, {comment,undefined}, {emu_args,undefined},
    +     {beam,<<70,79,82,49,0,0,3,68,66,69,65,77,65,116,
    +             111,109,0,0,0,83,0,0,0,9,...>>}]}
    +> os:cmd("escript demo.beam").
     "true"

    Here we create an archive script containing both Erlang code and Beam code, then we iterate over all files in the archive and collect their contents and some -information about them:

    > {ok, SourceCode} = file:read_file("demo.erl").
    -{ok,<<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}
    -> escript:create("demo.escript",
    -                 [shebang,
    -                  {archive, [{"demo.erl", SourceCode},
    -                             {"demo.beam", BeamCode}], []}]).
    -ok
    -> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined},
    -     {archive, ArchiveBin}]} = escript:extract("demo.escript", []).
    -{ok,[{shebang,default}, {comment,undefined}, {emu_args,undefined},
    -     {{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,
    -                152,61,93,107,0,0,0,118,0,...>>}]}
    -> file:write_file("demo.zip", ArchiveBin).
    -ok
    -> zip:foldl(fun(N, I, B, A) -> [{N, I(), B()} | A] end, [], "demo.zip").
    -{ok,[{"demo.beam",
    -      {file_info,748,regular,read_write,
    -                 {{2010,3,2},{0,59,22}},
    -                 {{2010,3,2},{0,59,22}},
    -                 {{2010,3,2},{0,59,22}},
    -                 54,1,0,0,0,0,0},
    -      <<70,79,82,49,0,0,2,228,66,69,65,77,65,116,111,109,0,0,0,
    -        83,0,0,...>>},
    -     {"demo.erl",
    -      {file_info,118,regular,read_write,
    -                 {{2010,3,2},{0,59,22}},
    -                 {{2010,3,2},{0,59,22}},
    -                 {{2010,3,2},{0,59,22}},
    -                 54,1,0,0,0,0,0},
    -      <<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}]}
    +information about them:

    > {ok, SourceCode} = file:read_file("demo.erl").
    +{ok,<<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}
    +> escript:create("demo.escript",
    +                 [shebang,
    +                  {archive, [{"demo.erl", SourceCode},
    +                             {"demo.beam", BeamCode}], []}]).
    +ok
    +> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined},
    +     {archive, ArchiveBin}]} = escript:extract("demo.escript", []).
    +{ok,[{shebang,default}, {comment,undefined}, {emu_args,undefined},
    +     {{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,
    +                152,61,93,107,0,0,0,118,0,...>>}]}
    +> file:write_file("demo.zip", ArchiveBin).
    +ok
    +> zip:foldl(fun(N, I, B, A) -> [{N, I(), B()} | A] end, [], "demo.zip").
    +{ok,[{"demo.beam",
    +      {file_info,748,regular,read_write,
    +                 {{2010,3,2},{0,59,22}},
    +                 {{2010,3,2},{0,59,22}},
    +                 {{2010,3,2},{0,59,22}},
    +                 54,1,0,0,0,0,0},
    +      <<70,79,82,49,0,0,2,228,66,69,65,77,65,116,111,109,0,0,0,
    +        83,0,0,...>>},
    +     {"demo.erl",
    +      {file_info,118,regular,read_write,
    +                 {{2010,3,2},{0,59,22}},
    +                 {{2010,3,2},{0,59,22}},
    +                 {{2010,3,2},{0,59,22}},
    +                 54,1,0,0,0,0,0},
    +      <<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}]}
    @@ -580,16 +580,16 @@ extracted value is set to the atom default. If a section is missing, the extracted value is set to the atom undefined.

    Option compile_source only affects the result if the escript contains source code. In this case the Erlang code is automatically compiled and -{source, BeamCode} is returned instead of {source, SourceCode}.

    Example:

    > escript:create("demo.escript",
    -                 [shebang, {archive, [{"demo.erl", SourceCode},
    -                                      {"demo.beam", BeamCode}], []}]).
    -ok
    -> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined},
    -     {archive, ArchiveBin}]} =
    -              escript:extract("demo.escript", []).
    -{ok,[{{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,
    -                152,61,93,107,0,0,0,118,0,...>>}
    -     {emu_args,undefined}]}
    +{source, BeamCode} is returned instead of {source, SourceCode}.

    Example:

    > escript:create("demo.escript",
    +                 [shebang, {archive, [{"demo.erl", SourceCode},
    +                                      {"demo.beam", BeamCode}], []}]).
    +ok
    +> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined},
    +     {archive, ArchiveBin}]} =
    +              escript:extract("demo.escript", []).
    +{ok,[{{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,
    +                152,61,93,107,0,0,0,118,0,...>>}
    +     {emu_args,undefined}]}
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ets.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1175)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ets.html 2026-08-21 04:00:29.097357735 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ets.html 2026-08-21 04:00:29.097357735 +0000 @@ -167,10 +167,10 @@ find the next key is not done with such guarantees. This is often not a problem, but may cause rare subtle "unexpected" effects if a concurrent process inserts objects during a traversal. For example, consider one process -doing

    ets:new(t, [ordered_set, named_table]),
    -ets:insert(t, {1}),
    -ets:insert(t, {2}),
    -ets:insert(t, {3}),

    A concurrent call to ets:first(t), done by another process, may then in rare +doing

    ets:new(t, [ordered_set, named_table]),
    +ets:insert(t, {1}),
    +ets:insert(t, {2}),
    +ets:insert(t, {3}),

    A concurrent call to ets:first(t), done by another process, may then in rare cases return 2 even though 2 has never existed in the table ordered as the first key. In the same way, a concurrent call to ets:next(t, 1) may return 3 even though 3 never existed in the table ordered directly after 1.

    Effects like this are improbable but possible. The probability will further be @@ -183,11 +183,11 @@ lookup without any table traversal at all. For ordered_set a partially bound key will limit the traversal to only scan a subset of the table based on term order. A partially bound key is either a list or a tuple with a prefix that is -fully bound. Example:

    1> T = ets:new(t,[ordered_set]), ets:insert(T, {"555-1234", "John Smith"}).
    +fully bound. Example:

    1> T = ets:new(t,[ordered_set]), ets:insert(T, {"555-1234", "John Smith"}).
     true
     2> %% Efficient search of all with area code 555
    -2> ets:match(T,{[$5,$5,$5,$- |'$1'],'$2'}).
    -[["1234","John Smith"]]

    Match Specifications

    Some of the functions use a match specification, match_spec. For a brief +2> ets:match(T,{[$5,$5,$5,$- |'$1'],'$2'}). +[["1234","John Smith"]]

    Match Specifications

    Some of the functions use a match specification, match_spec. For a brief explanation, see select/2. For a detailed description, see section Match Specifications in Erlang in ERTS User's Guide.

    A match specifications with excessive nesting will cause a system_limit error exception to be raised.

    @@ -1877,19 +1877,19 @@ -include_lib("stdlib/include/ms_transform.hrl"). to the source file.

    The fun is very restricted, it can take only a single parameter (the object to match): a sole variable or a tuple. It must use the is_ guard tests. Language constructs that have no representation in a match specification (if, case, -receive, and so on) are not allowed.

    The return value is the resulting match specification.

    Example:

    1> ets:fun2ms(fun({M,N}) when N > 3 -> M end).
    -[{{'$1','$2'},[{'>','$2',3}],['$1']}]

    Variables from the environment can be imported, so that the following works:

    2> X=3.
    +receive, and so on) are not allowed.

    The return value is the resulting match specification.

    Example:

    1> ets:fun2ms(fun({M,N}) when N > 3 -> M end).
    +[{{'$1','$2'},[{'>','$2',3}],['$1']}]

    Variables from the environment can be imported, so that the following works:

    2> X=3.
     3
    -3> ets:fun2ms(fun({M,N}) when N > X -> M end).
    -[{{'$1','$2'},[{'>','$2',{const,3}}],['$1']}]

    The imported variables are replaced by match specification const expressions, +3> ets:fun2ms(fun({M,N}) when N > X -> M end). +[{{'$1','$2'},[{'>','$2',{const,3}}],['$1']}]

    The imported variables are replaced by match specification const expressions, which is consistent with the static scoping for Erlang funs. However, local or global function calls cannot be in the guard or body of the fun. Calls to -built-in match specification functions is of course allowed:

    4> ets:fun2ms(fun({M,N}) when N > X, my_fun(M) -> M end).
    +built-in match specification functions is of course allowed:

    4> ets:fun2ms(fun({M,N}) when N > X, my_fun(M) -> M end).
     Error: fun containing local Erlang function calls
    -('my_fun' called in guard) cannot be translated into match_spec
    -{error,transform_error}
    -5> ets:fun2ms(fun({M,N}) when N > X, is_atom(M) -> M end).
    -[{{'$1','$2'},[{'>','$2',{const,3}},{is_atom,'$1'}],['$1']}]

    As shown by the example, the function can be called from the shell also. The fun +('my_fun' called in guard) cannot be translated into match_spec +{error,transform_error} +5> ets:fun2ms(fun({M,N}) when N > X, is_atom(M) -> M end). +[{{'$1','$2'},[{'>','$2',{const,3}},{is_atom,'$1'}],['$1']}]

    As shown by the example, the function can be called from the shell also. The fun must be literally in the call when used from the shell as well.

    Warning

    If the parse_transform is not applied to a module that calls this pseudo function, the call fails in runtime (with a badarg). The ets module exports a function with this name, but it is never to be called except when @@ -2514,12 +2514,12 @@

    Matches the objects in table Table against pattern Pattern.

    A pattern is a term that can contain:

    • Bound parts (Erlang terms)
    • '_' that matches any Erlang term
    • Pattern variables '$N', where N=0,1,...

    The function returns a list with one element for each matching object, where -each element is an ordered list of pattern variable bindings, for example:

    6> ets:match(T, '$1'). % Matches every object in table
    -[[{rufsen,dog,7}],[{brunte,horse,5}],[{ludde,dog,5}]]
    -7> ets:match(T, {'_',dog,'$1'}).
    -[[7],[5]]
    -8> ets:match(T, {'_',cow,'$1'}).
    -[]

    If the key is specified in the pattern, the match is very efficient. If the key +each element is an ordered list of pattern variable bindings, for example:

    6> ets:match(T, '$1'). % Matches every object in table
    +[[{rufsen,dog,7}],[{brunte,horse,5}],[{ludde,dog,5}]]
    +7> ets:match(T, {'_',dog,'$1'}).
    +[[7],[5]]
    +8> ets:match(T, {'_',cow,'$1'}).
    +[]

    If the key is specified in the pattern, the match is very efficient. If the key is not specified, that is, if it is a variable or an underscore, the entire table must be searched. The search time can be substantial if the table is very large.

    For tables of type ordered_set, the result is in the same order as in a @@ -2771,10 +2771,10 @@ execution time):

    Table = ets:new...
     MatchSpec = ...
     % The following call...
    -ets:match_spec_run(ets:tab2list(Table),
    -                   ets:match_spec_compile(MatchSpec)),
    +ets:match_spec_run(ets:tab2list(Table),
    +                   ets:match_spec_compile(MatchSpec)),
     % ...gives the same result as the more common (and more efficient)
    -ets:select(Table, MatchSpec),

    Note

    This function has limited use in normal code. It is used by the dets +ets:select(Table, MatchSpec),

    Note

    This function has limited use in normal code. It is used by the dets module to perform the dets:select/1 operations and by Mnesia during transactions.

    @@ -3142,19 +3142,19 @@ format. Given that the original match specification is kept intact, the continuation can be restored, meaning it can once again be used in subsequent select/1 calls even though it has been stored on disk or on -another node.

    Examples:

    The following sequence of calls may fail:

    T=ets:new(x,[]),
    +another node.

    Examples:

    The following sequence of calls may fail:

    T=ets:new(x,[]),
     ...
    -MS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end),
    -{_,C} = ets:select(T, MS, 10),
    -MaybeBroken = binary_to_term(term_to_binary(C)),
    -ets:select(MaybeBroken).

    The following sequence works, as the call to +MS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end), +{_,C} = ets:select(T, MS, 10), +MaybeBroken = binary_to_term(term_to_binary(C)), +ets:select(MaybeBroken).

    The following sequence works, as the call to repair_continuation/2 reestablishes the -MaybeBroken continuation.

    T=ets:new(x,[]),
    +MaybeBroken continuation.

    T=ets:new(x,[]),
     ...
    -MS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end),
    -{_,C} = ets:select(T,MS,10),
    -MaybeBroken = binary_to_term(term_to_binary(C)),
    -ets:select(ets:repair_continuation(MaybeBroken,MS)).

    Note

    This function is rarely needed in application code. It is used by Mnesia to +MS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end), +{_,C} = ets:select(T,MS,10), +MaybeBroken = binary_to_term(term_to_binary(C)), +ets:select(ets:repair_continuation(MaybeBroken,MS)).

    Note

    This function is rarely needed in application code. It is used by Mnesia to provide distributed select/3 and select/1 sequences. A normal application would either use Mnesia or keep the continuation from being converted to external format.

    The actual behavior of compiled match specifications when recreated from @@ -3199,21 +3199,21 @@ to succeed even if keys are removed during the traversal. The keys for objects inserted or deleted during a traversal may or may not be returned by next/2 depending on the ordering of keys within the table and if -the key exists at the time next/2 is called.

    Example:

    clean_all_with_value(Table,X) ->
    -    safe_fixtable(Table,true),
    -    clean_all_with_value(Table,X,ets:first(Table)),
    -    safe_fixtable(Table,false).
    +the key exists at the time next/2 is called.

    Example:

    clean_all_with_value(Table,X) ->
    +    safe_fixtable(Table,true),
    +    clean_all_with_value(Table,X,ets:first(Table)),
    +    safe_fixtable(Table,false).
     
    -clean_all_with_value(Table,X,'$end_of_table') ->
    +clean_all_with_value(Table,X,'$end_of_table') ->
         true;
    -clean_all_with_value(Table,X,Key) ->
    -    case ets:lookup(Table,Key) of
    -        [{Key,X}] ->
    -            ets:delete(Table,Key);
    +clean_all_with_value(Table,X,Key) ->
    +    case ets:lookup(Table,Key) of
    +        [{Key,X}] ->
    +            ets:delete(Table,Key);
             _ ->
                 true
         end,
    -    clean_all_with_value(Table,X,ets:next(Table,Key)).

    Notice that deleted objects are not freed from a fixed table until it has been + clean_all_with_value(Table,X,ets:next(Table,Key)).

    Notice that deleted objects are not freed from a fixed table until it has been released. If a process fixes a table but never releases it, the memory used by the deleted objects is never freed. The performance of operations on the table also degrades significantly.

    To retrieve information about which processes have fixed which tables, use @@ -3297,11 +3297,11 @@ object.

    The return value is constructed using the "match variables" bound in MatchHead or using the special match variables '$_' (the whole matching object) and '$$' (all match variables in a list), so that the following -match/2 expression:

    ets:match(Table,{'$1','$2','$3'})

    is exactly equivalent to:

    ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])

    And that the following match_object/2 call:

    ets:match_object(Table,{'$1','$2','$1'})

    is exactly equivalent to

    ets:select(Table,[{{'$1','$2','$1'},[],['$_']}])

    Composite terms can be constructed in the Result part either by simply writing -a list, so that the following code:

    ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])

    gives the same output as:

    ets:select(Table,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])

    That is, all the bound variables in the match head as a list. If tuples are to +match/2 expression:

    ets:match(Table,{'$1','$2','$3'})

    is exactly equivalent to:

    ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])

    And that the following match_object/2 call:

    ets:match_object(Table,{'$1','$2','$1'})

    is exactly equivalent to

    ets:select(Table,[{{'$1','$2','$1'},[],['$_']}])

    Composite terms can be constructed in the Result part either by simply writing +a list, so that the following code:

    ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])

    gives the same output as:

    ets:select(Table,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])

    That is, all the bound variables in the match head as a list. If tuples are to be constructed, one has to write a tuple of arity 1 where the single element in the tuple is the tuple one wants to construct (as an ordinary tuple can be -mistaken for a Guard).

    Therefore the following call:

    ets:select(Table,[{{'$1','$2','$1'},[],['$_']}])

    gives the same output as:

    ets:select(Table,[{{'$1','$2','$1'},[],[{{'$1','$2','$3'}}]}])

    This syntax is equivalent to the syntax used in the trace patterns (see the +mistaken for a Guard).

    Therefore the following call:

    ets:select(Table,[{{'$1','$2','$1'},[],['$_']}])

    gives the same output as:

    ets:select(Table,[{{'$1','$2','$1'},[],[{{'$1','$2','$3'}}]}])

    This syntax is equivalent to the syntax used in the trace patterns (see the dbg) module in Runtime_Tools.

    The Guards are constructed as tuples, where the first element is the test name and the remaining elements are the test parameters. To check for a specific type (say a list) of the element bound to the match variable '$1', one would write @@ -3310,7 +3310,7 @@ present in Erlang can be used, but only the new versions prefixed is_ are allowed (is_float, is_atom, and so on).

    The Guard section can also contain logic and arithmetic operations, which are written with the same syntax as the guard tests (prefix notation), so that the -following guard test written in Erlang:

    is_integer(X), is_integer(Y), X + Y < 4711

    is expressed as follows (X replaced with '$1' and Y with '$2'):

    [{is_integer, &#href_anchor"p" data-group-id="1124585429-2">}, {is_integer, '$2'}, {'<', {'+', '$1', '$2'}, 4711}]

    For tables of type ordered_set, objects are visited in the same order as in a +following guard test written in Erlang:

    is_integer(X), is_integer(Y), X + Y < 4711

    is expressed as follows (X replaced with '$1' and Y with '$2'):

    [{is_integer, &#href_anchor"p" data-group-id="8049382441-2">}, {is_integer, '$2'}, {'<', {'+', '$1', '$2'}, 4711}]

    For tables of type ordered_set, objects are visited in the same order as in a first/next traversal. This means that the match specification is executed against objects with keys in the first/next order and the corresponding result list is in the order of that execution.

    @@ -3462,16 +3462,16 @@ object. If not, select_replace will fail with badarg without updating any objects.

    For the moment, due to performance and semantic constraints, tables of type bag are not yet supported.

    The function returns the total number of replaced objects.

    Example

    For all 2-tuples with a list in second position, add atom 'marker' first in -the list:

    1> T = ets:new(x,[]), ets:insert(T, {key, [1, 2, 3]}).
    +the list:

    1> T = ets:new(x,[]), ets:insert(T, {key, [1, 2, 3]}).
     true
    -2> MS = ets:fun2ms(fun({K, L}) when is_list(L) -> {K, [marker | L]} end).
    -[{{'$1','$2'},[{is_list,'$2'}],[{{'$1',[marker|'$2']}}]}]
    -3> ets:select_replace(T, MS).
    +2> MS = ets:fun2ms(fun({K, L}) when is_list(L) -> {K, [marker | L]} end).
    +[{{'$1','$2'},[{is_list,'$2'}],[{{'$1',[marker|'$2']}}]}]
    +3> ets:select_replace(T, MS).
     1
    -4> ets:tab2list(T).
    -[{key,[marker,1,2,3]}]

    A generic single object compare-and-swap operation:

    [Old] = ets:lookup(T, Key),
    -New = update_object(Old),
    -Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
    +4>
    ets:tab2list(T). +[{key,[marker,1,2,3]}]

    A generic single object compare-and-swap operation:

    [Old] = ets:lookup(T, Key),
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/file_sorter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1046))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/file_sorter.html	2026-08-21 04:00:29.128357936 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/file_sorter.html	2026-08-21 04:00:29.129357943 +0000
    @@ -160,35 +160,35 @@
     argument {value, Value}. This makes it easy to initiate the sequence of output
     functions with a value calculated by the input functions.

    As an example, consider sorting the terms on a disk log file. A function that reads chunks from the disk log and returns a list of binaries is used as input. -The results are collected in a list of terms.

    sort(Log) ->
    -    {ok, _} = disk_log:open([{name,Log}, {mode,read_only}]),
    -    Input = input(Log, start),
    -    Output = output([]),
    -    Reply = file_sorter:sort(Input, Output, {format,term}),
    -    ok = disk_log:close(Log),
    +The results are collected in a list of terms.

    sort(Log) ->
    +    {ok, _} = disk_log:open([{name,Log}, {mode,read_only}]),
    +    Input = input(Log, start),
    +    Output = output([]),
    +    Reply = file_sorter:sort(Input, Output, {format,term}),
    +    ok = disk_log:close(Log),
         Reply.
     
    -input(Log, Cont) ->
    -    fun(close) ->
    +input(Log, Cont) ->
    +    fun(close) ->
                 ok;
    -       (read) ->
    -            case disk_log:chunk(Log, Cont) of
    -                {error, Reason} ->
    -                    {error, Reason};
    -                {Cont2, Terms} ->
    -                    {Terms, input(Log, Cont2)};
    -                {Cont2, Terms, _Badbytes} ->
    -                    {Terms, input(Log, Cont2)};
    +       (read) ->
    +            case disk_log:chunk(Log, Cont) of
    +                {error, Reason} ->
    +                    {error, Reason};
    +                {Cont2, Terms} ->
    +                    {Terms, input(Log, Cont2)};
    +                {Cont2, Terms, _Badbytes} ->
    +                    {Terms, input(Log, Cont2)};
                     eof ->
                         end_of_input
                 end
         end.
     
    -output(L) ->
    -    fun(close) ->
    -            lists:append(lists:reverse(L));
    -       (Terms) ->
    -            output([Terms | L])
    +output(L) ->
    +    fun(close) ->
    +            lists:append(lists:reverse(L));
    +       (Terms) ->
    +            output([Terms | L])
         end.

    For more examples of functions as input and output, see the end of the file_sorter module; the term format is implemented with functions.

    The possible values of Reason returned when an error occurs are:

    • bad_object, {bad_object, FileName} - Applying the format function failed for some binary, or the key(s) could not be extracted from some term.
    • {bad_term, FileName} - io:read/2 failed to read some term.
    • {file_error, FileName, file:posix()} - For an explanation of /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/filelib.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (915)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/filelib.html 2026-08-21 04:00:29.154358106 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/filelib.html 2026-08-21 04:00:29.160358145 +0000 @@ -995,15 +995,15 @@

      Sanitizes the relative path by eliminating ".." and "." components to protect against directory traversal attacks.

      Either returns the sanitized path name, or the atom unsafe if the path is unsafe. -The path is considered unsafe in the following circumstances:

      • The path is not relative.
      • A ".." component would climb up above the root of the relative path.
      • A symbolic link in the path points above the root of the relative path.

      Examples:

      1> {ok, Cwd} = file:get_cwd().
      +The path is considered unsafe in the following circumstances:

      • The path is not relative.
      • A ".." component would climb up above the root of the relative path.
      • A symbolic link in the path points above the root of the relative path.

      Examples:

      1> {ok, Cwd} = file:get_cwd().
       ...
      -2> filelib:safe_relative_path("dir/sub_dir/..", Cwd).
      +2> filelib:safe_relative_path("dir/sub_dir/..", Cwd).
       "dir"
      -3> filelib:safe_relative_path("dir/..", Cwd).
      -[]
      -4> filelib:safe_relative_path("dir/../..", Cwd).
      +3> filelib:safe_relative_path("dir/..", Cwd).
      +[]
      +4> filelib:safe_relative_path("dir/../..", Cwd).
       unsafe
      -5> filelib:safe_relative_path("/abs/path", Cwd).
      +5> filelib:safe_relative_path("/abs/path", Cwd).
       unsafe
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/filename.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1045)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/filename.html 2026-08-21 04:00:29.185358307 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/filename.html 2026-08-21 04:00:29.185358307 +0000 @@ -491,20 +491,20 @@

    Converts a relative Filename and returns an absolute name. No attempt is made to create the shortest absolute name, as this can give incorrect results on file -systems that allow links.

    Unix examples:

    1> pwd().
    +systems that allow links.

    Unix examples:

    1> pwd().
     "/usr/local"
    -2> filename:absname("foo").
    +2> filename:absname("foo").
     "/usr/local/foo"
    -3> filename:absname("../x").
    +3> filename:absname("../x").
     "/usr/local/../x"
    -4> filename:absname("/").
    -"/"

    Windows examples:

    1> pwd().
    +4> filename:absname("/").
    +"/"

    Windows examples:

    1> pwd().
     "D:/usr/local"
    -2> filename:absname("foo").
    +2> filename:absname("foo").
     "D:/usr/local/foo"
    -3> filename:absname("../x").
    +3> filename:absname("../x").
     "D:/usr/local/../x"
    -4> filename:absname("/").
    +4> filename:absname("/").
     "D:/"
    @@ -643,58 +643,58 @@

    Returns a suitable path, or paths, for a given type.

    If os is not set in Opts the function will default to the native option, that is 'linux', 'darwin' or 'windows', as understood by os:type/0. Anything not recognized as 'darwin' or 'windows' is interpreted as 'linux'.

    The options 'author' and 'version' are only used with 'windows' option -mode.

    • user_cache

      The path location is intended for transient data files on a local machine.

      On Linux: Respects the os environment variable XDG_CACHE_HOME.

      1> filename:basedir(user_cache, "my_application", #{os=>linux}).
      -"/home/otptest/.cache/my_application"

      On Darwin:

      1> filename:basedir(user_cache, "my_application", #{os=>darwin}).
      -"/home/otptest/Library/Caches/my_application"

      On Windows:

      1> filename:basedir(user_cache, "My App").
      +mode.

      • user_cache

        The path location is intended for transient data files on a local machine.

        On Linux: Respects the os environment variable XDG_CACHE_HOME.

        1> filename:basedir(user_cache, "my_application", #{os=>linux}).
        +"/home/otptest/.cache/my_application"

        On Darwin:

        1> filename:basedir(user_cache, "my_application", #{os=>darwin}).
        +"/home/otptest/Library/Caches/my_application"

        On Windows:

        1> filename:basedir(user_cache, "My App").
         "c:/Users/otptest/AppData/Local/My App/Cache"
        -2> filename:basedir(user_cache, "My App").
        +2> filename:basedir(user_cache, "My App").
         "c:/Users/otptest/AppData/Local/My App/Cache"
        -3> filename:basedir(user_cache, "My App", #{author=>"Erlang"}).
        +3> filename:basedir(user_cache, "My App", #{author=>"Erlang"}).
         "c:/Users/otptest/AppData/Local/Erlang/My App/Cache"
        -4> filename:basedir(user_cache, "My App", #{version=>"1.2"}).
        +4> filename:basedir(user_cache, "My App", #{version=>"1.2"}).
         "c:/Users/otptest/AppData/Local/My App/1.2/Cache"
        -5> filename:basedir(user_cache, "My App", #{author=>"Erlang",version=>"1.2"}).
        -"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Cache"
      • user_config

        The path location is intended for persistent configuration files.

        On Linux: Respects the os environment variable XDG_CONFIG_HOME.

        2> filename:basedir(user_config, "my_application", #{os=>linux}).
        -"/home/otptest/.config/my_application"

        On Darwin:

        2> filename:basedir(user_config, "my_application", #{os=>darwin}).
        -"/home/otptest/Library/Application Support/my_application"

        On Windows:

        1> filename:basedir(user_config, "My App").
        +5> filename:basedir(user_cache, "My App", #{author=>"Erlang",version=>"1.2"}).
        +"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Cache"
      • user_config

        The path location is intended for persistent configuration files.

        On Linux: Respects the os environment variable XDG_CONFIG_HOME.

        2> filename:basedir(user_config, "my_application", #{os=>linux}).
        +"/home/otptest/.config/my_application"

        On Darwin:

        2> filename:basedir(user_config, "my_application", #{os=>darwin}).
        +"/home/otptest/Library/Application Support/my_application"

        On Windows:

        1> filename:basedir(user_config, "My App").
         "c:/Users/otptest/AppData/Roaming/My App"
        -2> filename:basedir(user_config, "My App", #{author=>"Erlang", version=>"1.2"}).
        -"c:/Users/otptest/AppData/Roaming/Erlang/My App/1.2"
      • user_data

        The path location is intended for persistent data files.

        On Linux: Respects the os environment variable XDG_DATA_HOME.

        3> filename:basedir(user_data, "my_application", #{os=>linux}).
        -"/home/otptest/.local/my_application"

        On Darwin:

        3> filename:basedir(user_data, "my_application", #{os=>darwin}).
        -"/home/otptest/Library/Application Support/my_application"

        On Windows:

        8> filename:basedir(user_data, "My App").
        +2> filename:basedir(user_config, "My App", #{author=>"Erlang", version=>"1.2"}).
        +"c:/Users/otptest/AppData/Roaming/Erlang/My App/1.2"
      • user_data

        The path location is intended for persistent data files.

        On Linux: Respects the os environment variable XDG_DATA_HOME.

        3> filename:basedir(user_data, "my_application", #{os=>linux}).
        +"/home/otptest/.local/my_application"

        On Darwin:

        3> filename:basedir(user_data, "my_application", #{os=>darwin}).
        +"/home/otptest/Library/Application Support/my_application"

        On Windows:

        8> filename:basedir(user_data, "My App").
         "c:/Users/otptest/AppData/Local/My App"
        -9> filename:basedir(user_data, "My App",#{author=>"Erlang",version=>"1.2"}).
        -"c:/Users/otptest/AppData/Local/Erlang/My App/1.2"
      • user_log

        The path location is intended for transient log files on a local machine.

        On Linux: Respects the os environment variable XDG_CACHE_HOME.

        4> filename:basedir(user_log, "my_application", #{os=>linux}).
        -"/home/otptest/.cache/my_application/log"

        On Darwin:

        4> filename:basedir(user_log, "my_application", #{os=>darwin}).
        -"/home/otptest/Library/Logs/my_application"

        On Windows:

        12> filename:basedir(user_log, "My App").
        +9> filename:basedir(user_data, "My App",#{author=>"Erlang",version=>"1.2"}).
        +"c:/Users/otptest/AppData/Local/Erlang/My App/1.2"
      • user_log

        The path location is intended for transient log files on a local machine.

        On Linux: Respects the os environment variable XDG_CACHE_HOME.

        4> filename:basedir(user_log, "my_application", #{os=>linux}).
        +"/home/otptest/.cache/my_application/log"

        On Darwin:

        4> filename:basedir(user_log, "my_application", #{os=>darwin}).
        +"/home/otptest/Library/Logs/my_application"

        On Windows:

        12> filename:basedir(user_log, "My App").
         "c:/Users/otptest/AppData/Local/My App/Logs"
        -13> filename:basedir(user_log, "My App",#{author=>"Erlang",version=>"1.2"}).
        -"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Logs"
      • site_config

        On Linux: Respects the os environment variable XDG_CONFIG_DIRS.

        5> filename:basedir(site_config, "my_application", #{os=>linux}).
        -["/usr/local/share/my_application",
        - "/usr/share/my_application"]
        -6> os:getenv("XDG_CONFIG_DIRS").
        +13> filename:basedir(user_log, "My App",#{author=>"Erlang",version=>"1.2"}).
        +"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Logs"
      • site_config

        On Linux: Respects the os environment variable XDG_CONFIG_DIRS.

        5> filename:basedir(site_config, "my_application", #{os=>linux}).
        +["/usr/local/share/my_application",
        + "/usr/share/my_application"]
        +6> os:getenv("XDG_CONFIG_DIRS").
         "/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg"
        -7> filename:basedir(site_config, "my_application", #{os=>linux}).
        -["/etc/xdg/xdg-ubuntu/my_application",
        +7> filename:basedir(site_config, "my_application", #{os=>linux}).
        +["/etc/xdg/xdg-ubuntu/my_application",
          "/usr/share/upstart/xdg/my_application",
        - "/etc/xdg/my_application"]
        -8> os:unsetenv("XDG_CONFIG_DIRS").
        + "/etc/xdg/my_application"]
        +8> os:unsetenv("XDG_CONFIG_DIRS").
         true
        -9> filename:basedir(site_config, "my_application", #{os=>linux}).
        -["/etc/xdg/my_application"]

        On Darwin:

        5> filename:basedir(site_config, "my_application", #{os=>darwin}).
        -["/Library/Application Support/my_application"]
      • site_data

        On Linux: Respects the os environment variable XDG_DATA_DIRS.

        10> os:getenv("XDG_DATA_DIRS").
        +9> filename:basedir(site_config, "my_application", #{os=>linux}).
        +["/etc/xdg/my_application"]

        On Darwin:

        5> filename:basedir(site_config, "my_application", #{os=>darwin}).
        +["/Library/Application Support/my_application"]
      • site_data

        On Linux: Respects the os environment variable XDG_DATA_DIRS.

        10> os:getenv("XDG_DATA_DIRS").
         "/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/"
        -11> filename:basedir(site_data, "my_application", #{os=>linux}).
        -["/usr/share/ubuntu/my_application",
        +11> filename:basedir(site_data, "my_application", #{os=>linux}).
        +["/usr/share/ubuntu/my_application",
          "/usr/share/gnome/my_application",
          "/usr/local/share/my_application",
        - "/usr/share/my_application"]
        -12> os:unsetenv("XDG_DATA_DIRS").
        + "/usr/share/my_application"]
        +12> os:unsetenv("XDG_DATA_DIRS").
         true
        -13> filename:basedir(site_data, "my_application", #{os=>linux}).
        -["/usr/local/share/my_application",
        - "/usr/share/my_application"]

        On Darwin:

        5> filename:basedir(site_data, "my_application", #{os=>darwin}).
        -["/Library/Application Support/my_application"]
      +13>
      filename:basedir(site_data, "my_application", #{os=>linux}). +["/usr/local/share/my_application", + "/usr/share/my_application"]

      On Darwin:

      5> filename:basedir(site_data, "my_application", #{os=>darwin}).
      +["/Library/Application Support/my_application"]
    @@ -723,12 +723,12 @@

    Returns the last component of Filename, or Filename itself if it does not -contain any directory separators.

    Examples:

    5> filename:basename("foo").
    +contain any directory separators.

    Examples:

    5> filename:basename("foo").
     "foo"
    -6> filename:basename("/usr/foo").
    +6> filename:basename("/usr/foo").
     "foo"
    -7> filename:basename("/").
    -[]
    +7>
    filename:basename("/"). +[]
    @@ -759,15 +759,15 @@

    Returns the last component of Filename with extension Ext stripped.

    This function is to be used to remove a (possible) specific extension. To remove an existing extension when you are unsure which one it is, use -rootname(basename(Filename)).

    Examples:

    8> filename:basename("~/src/kalle.erl", ".erl").
    +rootname(basename(Filename)).

    Examples:

    8> filename:basename("~/src/kalle.erl", ".erl").
     "kalle"
    -9> filename:basename("~/src/kalle.beam", ".erl").
    +9> filename:basename("~/src/kalle.beam", ".erl").
     "kalle.beam"
    -10> filename:basename("~/src/kalle.old.erl", ".erl").
    +10> filename:basename("~/src/kalle.old.erl", ".erl").
     "kalle.old"
    -11> filename:rootname(filename:basename("~/src/kalle.erl")).
    +11> filename:rootname(filename:basename("~/src/kalle.erl")).
     "kalle"
    -12> filename:rootname(filename:basename("~/src/kalle.beam")).
    +12> filename:rootname(filename:basename("~/src/kalle.beam")).
     "kalle"
    @@ -796,10 +796,10 @@ -

    Returns the directory part of Filename.

    Examples:

    13> filename:dirname("/usr/src/kalle.erl").
    +

    Returns the directory part of Filename.

    Examples:

    13> filename:dirname("/usr/src/kalle.erl").
     "/usr/src"
    -14> filename:dirname("kalle.erl").
    -"."
    5> filename:dirname("\\usr\\src/kalle.erl"). % Windows
    +14> filename:dirname("kalle.erl").
    +"."
    5> filename:dirname("\\usr\\src/kalle.erl"). % Windows
     "/usr/src"
    @@ -829,10 +829,10 @@

    Returns the file extension of Filename, including the period. Returns an empty -string if no extension exists.

    Examples:

    15> filename:extension("foo.erl").
    +string if no extension exists.

    Examples:

    15> filename:extension("foo.erl").
     ".erl"
    -16> filename:extension("beam.src/kalle").
    -[]
    +16>
    filename:extension("beam.src/kalle"). +[]
    @@ -892,10 +892,10 @@

    Joins a list of filename Components with directory separators. If one of the elements of Components includes an absolute path, such as "/xxx", the preceding elements, if any, are removed from the result.

    The result is "normalized":

    • Redundant directory separators are removed.
    • In Windows, all directory separators are forward slashes and the drive letter -is in lower case.

    Examples:

    17> filename:join(["/usr", "local", "bin"]).
    +is in lower case.

    Examples:

    17> filename:join(["/usr", "local", "bin"]).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gb_sets.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1505))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gb_sets.html	2026-08-21 04:00:29.222358548 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gb_sets.html	2026-08-21 04:00:29.222358548 +0000
    @@ -799,14 +799,14 @@
     
           
     
    -

    Returns a new set formed from Set1 with Element inserted.

    If Element is already an element in Set1, nothing is changed.

    Examples

    1> S0 = gb_sets:new().
    -2> S1 = gb_sets:add_element(7, S0).
    -3> gb_sets:to_list(S1).
    -[7]
    -4> S2 = gb_sets:add_element(42, S1).
    -5> S2 = gb_sets:add_element(42, S1).
    -6> gb_sets:to_list(S2).
    -[7,42]
    +

    Returns a new set formed from Set1 with Element inserted.

    If Element is already an element in Set1, nothing is changed.

    Examples

    1> S0 = gb_sets:new().
    +2> S1 = gb_sets:add_element(7, S0).
    +3> gb_sets:to_list(S1).
    +[7]
    +4> S2 = gb_sets:add_element(42, S1).
    +5> S2 = gb_sets:add_element(42, S1).
    +6> gb_sets:to_list(S2).
    +[7,42]
    @@ -837,12 +837,12 @@

    Rebalances the tree representation of Set1.

    This is rarely necessary, but can be motivated when a large number of elements have been deleted from the tree without further insertions. Forcing rebalancing can minimize lookup times, as deletion -does not rebalance the tree.

    Examples

    1> S0 = gb_sets:from_ordset(lists:seq(1, 100)).
    -2> Delete = fun(E, Set) -> gb_sets:delete(E, Set) end.
    -3> S1 = lists:foldl(Delete, S0, lists:seq(1, 50)).
    -4> gb_sets:size(S1).
    +does not rebalance the tree.

    Examples

    1> S0 = gb_sets:from_ordset(lists:seq(1, 100)).
    +2> Delete = fun(E, Set) -> gb_sets:delete(E, Set) end.
    +3> S1 = lists:foldl(Delete, S0, lists:seq(1, 50)).
    +4> gb_sets:size(S1).
     50
    -5> S2 = gb_sets:balance(S1).
    +5>
    S2 = gb_sets:balance(S1).
    @@ -900,9 +900,9 @@

    Returns a new set formed from Set1 with Element removed, assuming Element is present in Set1.

    Use delete_any/2 when deleting from a set where Element is potentially -missing.

    Examples

    1> S = gb_sets:from_list([a,b]).
    -2> gb_sets:to_list(gb_sets:delete(b, S)).
    -[a]
    +missing.

    Examples

    1> S = gb_sets:from_list([a,b]).
    +2> gb_sets:to_list(gb_sets:delete(b, S)).
    +[a]
    @@ -930,10 +930,10 @@ -

    Returns a new set formed from Set1 with Element removed.

    If Element is not an element in Set1, nothing is changed.

    Examples

    1> S = gb_sets:from_list([a,b]).
    -2> gb_sets:to_list(gb_sets:delete_any(b, S)).
    -[a]
    -3> S = gb_sets:delete_any(x, S).
    +

    Returns a new set formed from Set1 with Element removed.

    If Element is not an element in Set1, nothing is changed.

    Examples

    1> S = gb_sets:from_list([a,b]).
    +2> gb_sets:to_list(gb_sets:delete_any(b, S)).
    +[a]
    +3> S = gb_sets:delete_any(x, S).
    @@ -990,8 +990,8 @@ -

    Returns a new empty set.

    Examples

    1> gb_sets:to_list(gb_sets:empty()).
    -[]
    +

    Returns a new empty set.

    Examples

    1> gb_sets:to_list(gb_sets:empty()).
    +[]
    @@ -1020,11 +1020,11 @@ -

    Filters elements in Set1 using predicate function Pred.

    Examples

    1> S = gb_sets:from_list([1,2,3,4,5,6,7]).
    -2> IsEven = fun(N) -> N rem 2 =:= 0 end.
    -3> Filtered = gb_sets:filter(IsEven, S).
    -4> gb_sets:to_list(Filtered).
    -[2,4,6]
    +

    Filters elements in Set1 using predicate function Pred.

    Examples

    1> S = gb_sets:from_list([1,2,3,4,5,6,7]).
    +2> IsEven = fun(N) -> N rem 2 =:= 0 end.
    +3> Filtered = gb_sets:filter(IsEven, S).
    +4> gb_sets:to_list(Filtered).
    +[2,4,6]
    @@ -1061,17 +1061,17 @@

    Calls Fun(Elem) for each Elem of Set1 to update or remove elements from Set1.

    Fun/1 must return either a Boolean or a tuple {true, Value}. The function returns the set of elements for which Fun returns a new -value, with true being equivalent to {true, Elem}.

    gb_sets:filtermap/2 behaves as if it were defined as follows:

    filtermap(Fun, Set1) ->
    -    gb_sets:from_list(lists:filtermap(Fun, Set1)).

    Examples

    1> S = gb_sets:from_list([2,4,5,6,8,9])
    -2> F = fun(X) ->
    +value, with true being equivalent to {true, Elem}.

    gb_sets:filtermap/2 behaves as if it were defined as follows:

    filtermap(Fun, Set1) ->
    +    gb_sets:from_list(lists:filtermap(Fun, Set1)).

    Examples

    1> S = gb_sets:from_list([2,4,5,6,8,9])
    +2> F = fun(X) ->
                case X rem 2 of
    -               0 -> {true, X div 2};
    +               0 -> {true, X div 2};
                    1 -> false
                end
             end.
    -3> Set = gb_sets:filtermap(F, S).
    -4> gb_sets:to_list(Set).
    -[1,2,3,4]
    +3>
    Set = gb_sets:filtermap(F, S). +4> gb_sets:to_list(Set). +[1,2,3,4]
    @@ -1107,9 +1107,9 @@

    Folds Function over every element in Set and returns the final value of -the accumulator.

    Examples

    1> S = gb_sets:from_list([1,2,3,4]).
    +the accumulator.

    Examples

    1> S = gb_sets:from_list([1,2,3,4]).
     2> Plus = fun erlang:'+'/2.
    -3> gb_sets:fold(Plus, 0, S).
    +3> gb_sets:fold(Plus, 0, S).
     10
    @@ -1139,9 +1139,9 @@

    Returns a set of the elements in List, where List can be unordered and -contain duplicates.

    Examples

    1> Unordered = [x,y,a,x,y,b,b,z]
    -2> gb_sets:to_list(gb_sets:from_list(Unordered)).
    -[a,b,x,y,z]
    +contain duplicates.

    Examples

    1> Unordered = [x,y,a,x,y,b,b,z]
    +2> gb_sets:to_list(gb_sets:from_list(Unordered)).
    +[a,b,x,y,z]
    @@ -1170,9 +1170,9 @@

    Turns an ordered list without duplicates List into a set.

    See from_list/1 for a function that accepts unordered lists with -duplicates.

    Examples

    1> Ordset = [1,2,3].
    -2> gb_sets:to_list(gb_sets:from_ordset(Ordset)).
    -[1,2,3]
    +duplicates.

    Examples

    1> Ordset = [1,2,3].
    +2> gb_sets:to_list(gb_sets:from_ordset(Ordset)).
    +[1,2,3]
    @@ -1202,13 +1202,13 @@

    Returns a new set formed from Set1 with Element inserted, assuming Element is not already present.

    Use add/2 for inserting into a set where Element is potentially -already present.

    Examples

    1> S0 = gb_sets:new().
    -2> S1 = gb_sets:insert(7, S0).
    -3> gb_sets:to_list(S1).
    -[7]
    -4> S2 = gb_sets:insert(42, S1).
    -5> gb_sets:to_list(S2).
    -[7,42]
    +already present.

    Examples

    1> S0 = gb_sets:new().
    +2> S1 = gb_sets:insert(7, S0).
    +3> gb_sets:to_list(S1).
    +[7]
    +4> S2 = gb_sets:insert(42, S1).
    +5> gb_sets:to_list(S2).
    +[7,42]
    @@ -1237,15 +1237,15 @@

    Returns the intersection of the non-empty list of sets.

    The intersection of multiple sets is a new set that contains only the -elements that are present in all sets.

    Examples

    1> S0 = gb_sets:from_list([a,b,c,d]).
    -2> S1 = gb_sets:from_list([d,e,f]).
    -3> S2 = gb_sets:from_list([q,r])
    -4> Sets = [S0, S1, S2].
    -5> gb_sets:to_list(gb_sets:intersection([S0, S1, S2])).
    -[]
    -6> gb_sets:to_list(gb_sets:intersection([S0, S1])).
    -[d]
    -7> gb_sets:intersection([]).
    +elements that are present in all sets.

    Examples

    1> S0 = gb_sets:from_list([a,b,c,d]).
    +2> S1 = gb_sets:from_list([d,e,f]).
    +3> S2 = gb_sets:from_list([q,r])
    +4> Sets = [S0, S1, S2].
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_event.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_event.html	2026-08-21 04:00:29.264358822 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_event.html	2026-08-21 04:00:29.265358828 +0000
    @@ -1262,15 +1262,15 @@
     but it may transform some values.

    Two possible use cases for this callback is to remove sensitive information from the state to prevent it from being printed in log files, or to compact large irrelevant status items -that would only clutter the logs.

    Example:

    format_status(Status) ->
    -  maps:map(
    -    fun(state,State) ->
    -            maps:remove(private_key, State);
    -       (message,{password, _Pass}) ->
    -            {password, removed};
    -       (_,Value) ->
    +that would only clutter the logs.

    Example:

    format_status(Status) ->
    +  maps:map(
    +    fun(state,State) ->
    +            maps:remove(private_key, State);
    +       (message,{password, _Pass}) ->
    +            {password, removed};
    +       (_,Value) ->
                 Value
    -    end, Status).

    Note

    This callback is optional, so event handler modules need not export it. + end, Status).

    Note

    This callback is optional, so event handler modules need not export it. If a handler does not export this function, the gen_event module uses the handler state directly for the purposes described below.

    If this callback is exported but fails, to hide possibly sensitive data, the default function will instead return the fact that /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_fsm.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1379)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_fsm.html 2026-08-21 04:00:29.305359089 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_fsm.html 2026-08-21 04:00:29.305359089 +0000 @@ -94,163 +94,163 @@

    Deprecated and replaced by gen_statem in OTP 20.

    Migration to gen_statem

    Here follows a simple example of turning a gen_fsm into a gen_statem. -The example comes from the previous User's Guide for gen_fsm

    -module(code_lock).
    --define(NAME, code_lock).
    +The example comes from the previous User's Guide for gen_fsm

    -module(code_lock).
    +-define(NAME, code_lock).
     %-define(BEFORE_REWRITE, true).
     
    --ifdef(BEFORE_REWRITE).
    --behaviour(gen_fsm).
    +-ifdef(BEFORE_REWRITE).
    +-behaviour(gen_fsm).
     -else.
    --behaviour(gen_statem).
    +-behaviour(gen_statem).
     -endif.
     
    --export([start_link/1, button/1, stop/0]).
    +-export([start_link/1, button/1, stop/0]).
     
    --ifdef(BEFORE_REWRITE).
    --export([init/1, locked/2, open/2, handle_sync_event/4, handle_event/3,
    -     handle_info/3, terminate/3, code_change/4]).
    +-ifdef(BEFORE_REWRITE).
    +-export([init/1, locked/2, open/2, handle_sync_event/4, handle_event/3,
    +     handle_info/3, terminate/3, code_change/4]).
     -else.
    --export([init/1, callback_mode/0, locked/3, open/3,
    -     terminate/3, code_change/4]).
    +-export([init/1, callback_mode/0, locked/3, open/3,
    +     terminate/3, code_change/4]).
     %% Add callback__mode/0
     %% Change arity of the state functions
     %% Remove handle_info/3
     -endif.
     
    --ifdef(BEFORE_REWRITE).
    -start_link(Code) ->
    -    gen_fsm:start_link({local, ?NAME}, ?MODULE, Code, []).
    +-ifdef(BEFORE_REWRITE).
    +start_link(Code) ->
    +    gen_fsm:start_link({local, ?NAME}, ?MODULE, Code, []).
     -else.
    -start_link(Code) ->
    -    gen_statem:start_link({local,?NAME}, ?MODULE, Code, []).
    +start_link(Code) ->
    +    gen_statem:start_link({local,?NAME}, ?MODULE, Code, []).
     -endif.
     
    --ifdef(BEFORE_REWRITE).
    -button(Digit) ->
    -    gen_fsm:send_event(?NAME, {button, Digit}).
    +-ifdef(BEFORE_REWRITE).
    +button(Digit) ->
    +    gen_fsm:send_event(?NAME, {button, Digit}).
     -else.
    -button(Digit) ->
    -    gen_statem:cast(?NAME, {button,Digit}).
    +button(Digit) ->
    +    gen_statem:cast(?NAME, {button,Digit}).
         %% send_event is asynchronous and becomes a cast
     -endif.
     
    --ifdef(BEFORE_REWRITE).
    -stop() ->
    -    gen_fsm:sync_send_all_state_event(?NAME, stop).
    +-ifdef(BEFORE_REWRITE).
    +stop() ->
    +    gen_fsm:sync_send_all_state_event(?NAME, stop).
     -else.
    -stop() ->
    -    gen_statem:call(?NAME, stop).
    +stop() ->
    +    gen_statem:call(?NAME, stop).
         %% sync_send is synchronous and becomes call
         %% all_state is handled by callback code in gen_statem
     -endif.
     
    -init(Code) ->
    -    do_lock(),
    -    Data = #href_anchor"ss">code => Code, remaining => Code},
    -    {ok, locked, Data}.
    +init(Code) ->
    +    do_lock(),
    +    Data = #href_anchor"ss">code => Code, remaining => Code},
    +    {ok, locked, Data}.
     
    --ifdef(BEFORE_REWRITE).
    +-ifdef(BEFORE_REWRITE).
     -else.
    -callback_mode() ->
    +callback_mode() ->
         state_functions.
     %% state_functions mode is the mode most similar to
     %% gen_fsm. There is also handle_event mode which is
     %% a fairly different concept.
     -endif.
     
    --ifdef(BEFORE_REWRITE).
    -locked({button, Digit}, Data0) ->
    -    case analyze_lock(Digit, Data0) of
    -    {open = StateName, Data} ->
    -        {next_state, StateName, Data, 10000};
    -    {StateName, Data} ->
    -        {next_state, StateName, Data}
    +-ifdef(BEFORE_REWRITE).
    +locked({button, Digit}, Data0) ->
    +    case analyze_lock(Digit, Data0) of
    +    {open = StateName, Data} ->
    +        {next_state, StateName, Data, 10000};
    +    {StateName, Data} ->
    +        {next_state, StateName, Data}
         end.
     -else.
    -locked(cast, {button,Digit}, Data0) ->
    -    case analyze_lock(Digit, Data0) of
    -    {open = StateName, Data} ->
    -        {next_state, StateName, Data, 10000};
    -    {StateName, Data} ->
    -        {next_state, StateName, Data}
    +locked(cast, {button,Digit}, Data0) ->
    +    case analyze_lock(Digit, Data0) of
    +    {open = StateName, Data} ->
    +        {next_state, StateName, Data, 10000};
    +    {StateName, Data} ->
    +        {next_state, StateName, Data}
         end;
    -locked({call, From}, Msg, Data) ->
    -    handle_call(From, Msg, Data);
    -locked({info, Msg}, StateName, Data) ->
    -    handle_info(Msg, StateName, Data).
    +locked({call, From}, Msg, Data) ->
    +    handle_call(From, Msg, Data);
    +locked({info, Msg}, StateName, Data) ->
    +    handle_info(Msg, StateName, Data).
     %% Arity differs
     %% All state events are dispatched to handle_call and handle_info help
     %% functions. If you want to handle a call or cast event specifically
     %% for this state you would add a special clause for it above.
     -endif.
     
    --ifdef(BEFORE_REWRITE).
    -open(timeout, State) ->
    -     do_lock(),
    -    {next_state, locked, State};
    -open({button,_}, Data) ->
    -    {next_state, locked, Data}.
    --else.
    -open(timeout, _, Data) ->
    -    do_lock(),
    -    {next_state, locked, Data};
    -open(cast, {button,_}, Data) ->
    -    {next_state, locked, Data};
    -open({call, From}, Msg, Data) ->
    -    handle_call(From, Msg, Data);
    -open(info, Msg, Data) ->
    -    handle_info(Msg, open, Data).
    +-ifdef(BEFORE_REWRITE).
    +open(timeout, State) ->
    +     do_lock(),
    +    {next_state, locked, State};
    +open({button,_}, Data) ->
    +    {next_state, locked, Data}.
    +-else.
    +open(timeout, _, Data) ->
    +    do_lock(),
    +    {next_state, locked, Data};
    +open(cast, {button,_}, Data) ->
    +    {next_state, locked, Data};
    +open({call, From}, Msg, Data) ->
    +    handle_call(From, Msg, Data);
    +open(info, Msg, Data) ->
    +    handle_info(Msg, open, Data).
     %% Arity differs
     %% All state events are dispatched to handle_call and handle_info help
     %% functions. If you want to handle a call or cast event specifically
     %% for this state you would add a special clause for it above.
     -endif.
     
    --ifdef(BEFORE_REWRITE).
    -handle_sync_event(stop, _From, _StateName, Data) ->
    -    {stop, normal, ok, Data}.
    +-ifdef(BEFORE_REWRITE).
    +handle_sync_event(stop, _From, _StateName, Data) ->
    +    {stop, normal, ok, Data}.
     
    -handle_event(Event, StateName, Data) ->
    -    {stop, {shutdown, {unexpected, Event, StateName}}, Data}.
    +handle_event(Event, StateName, Data) ->
    +    {stop, {shutdown, {unexpected, Event, StateName}}, Data}.
     
    -handle_info(Info, StateName, Data) ->
    -    {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.
    +handle_info(Info, StateName, Data) ->
    +    {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.
     -else.
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_server.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_server.html	2026-08-21 04:00:29.351359388 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_server.html	2026-08-21 04:00:29.351359388 +0000
    @@ -1360,15 +1360,15 @@
     but it may transform some values.

    Two possible use cases for this callback is to remove sensitive information from the state to prevent it from being printed in log files, or to compact large irrelevant status items -that would only clutter the logs.

    Example:

    format_status(Status) ->
    -  maps:map(
    -    fun(state,State) ->
    -            maps:remove(private_key, State);
    -       (message,{password, _Pass}) ->
    -            {password, removed};
    -       (_,Value) ->
    +that would only clutter the logs.

    Example:

    format_status(Status) ->
    +  maps:map(
    +    fun(state,State) ->
    +            maps:remove(private_key, State);
    +       (message,{password, _Pass}) ->
    +            {password, removed};
    +       (_,Value) ->
                 Value
    -    end, Status).

    Note

    This callback is optional, so callback modules need not export it. The + end, Status).

    Note

    This callback is optional, so callback modules need not export it. The gen_server module provides a default implementation of this function that returns the callback module state.

    If this callback is exported but fails, to hide possibly sensitive data, /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_statem.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (956)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_statem.html 2026-08-21 04:00:29.408359759 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/gen_statem.html 2026-08-21 04:00:29.410359772 +0000 @@ -141,7 +141,7 @@ depending on callback mode Release upgrade/downgrade -(code change) +(code change) -----> Module:code_change/4

    State callback

    The state callback for a specific state in a gen_statem is the callback function that is called for all events in this state. It is selected depending on which callback mode @@ -249,97 +249,97 @@ on --> off : push\n* Reply 'off'

    Not shown in the state diagram:

    • The API function push() generates an event push of type call.
    • The API function get_count() generates an event get_count of type call that is handled in all states by replying with the current count value.
    • Unknown events are ignored and discarded.
    • There is boilerplate code for start, stop, terminate, code change, -init, to set the callback mode to state_functions, etc...

    Pushbutton Code

    The following is the complete callback module file pushbutton.erl:

    -module(pushbutton).
    --behaviour(gen_statem).
    +init, to set the callback mode to state_functions, etc...

    Pushbutton Code

    The following is the complete callback module file pushbutton.erl:

    -module(pushbutton).
    +-behaviour(gen_statem).
     
    --export([start/0,push/0,get_count/0,stop/0]).
    --export([terminate/3,code_change/4,init/1,callback_mode/0]).
    --export([on/3,off/3]).
    +-export([start/0,push/0,get_count/0,stop/0]).
    +-export([terminate/3,code_change/4,init/1,callback_mode/0]).
    +-export([on/3,off/3]).
     
    -name() -> pushbutton_statem. % The registered server name
    +name() -> pushbutton_statem. % The registered server name
     
     %% API.  This example uses a registered name name()
     %% and does not link to the caller.
    -start() ->
    -    gen_statem:start({local,name()}, ?MODULE, [], []).
    -push() ->
    -    gen_statem:call(name(), push).
    -get_count() ->
    -    gen_statem:call(name(), get_count).
    -stop() ->
    -    gen_statem:stop(name()).
    +start() ->
    +    gen_statem:start({local,name()}, ?MODULE, [], []).
    +push() ->
    +    gen_statem:call(name(), push).
    +get_count() ->
    +    gen_statem:call(name(), get_count).
    +stop() ->
    +    gen_statem:stop(name()).
     
     %% Mandatory callback functions
    -terminate(_Reason, _State, _Data) ->
    +terminate(_Reason, _State, _Data) ->
         void.
    -code_change(_Vsn, State, Data, _Extra) ->
    -    {ok,State,Data}.
    -init([]) ->
    +code_change(_Vsn, State, Data, _Extra) ->
    +    {ok,State,Data}.
    +init([]) ->
         %% Set the initial state + data.  Data is used only as a counter.
         State = off, Data = 0,
    -    {ok,State,Data}.
    -callback_mode() -> state_functions.
    +    {ok,State,Data}.
    +callback_mode() -> state_functions.
     
     %%% state callback(s)
     
    -off({call,From}, push, Data) ->
    +off({call,From}, push, Data) ->
         %% Go to 'on', increment count and reply
         %% that the resulting status is 'on'
    -    {next_state,on,Data+1,[{reply,From,on}]};
    -off(EventType, EventContent, Data) ->
    -    handle_event(EventType, EventContent, Data).
    +    {next_state,on,Data+1,[{reply,From,on}]};
    +off(EventType, EventContent, Data) ->
    +    handle_event(EventType, EventContent, Data).
     
    -on({call,From}, push, Data) ->
    +on({call,From}, push, Data) ->
         %% Go to 'off' and reply that the resulting status is 'off'
    -    {next_state,off,Data,[{reply,From,off}]};
    -on(EventType, EventContent, Data) ->
    -    handle_event(EventType, EventContent, Data).
    +    {next_state,off,Data,[{reply,From,off}]};
    +on(EventType, EventContent, Data) ->
    +    handle_event(EventType, EventContent, Data).
     
     %% Handle events common to all states
    -handle_event({call,From}, get_count, Data) ->
    +handle_event({call,From}, get_count, Data) ->
         %% Reply with the current count
    -    {keep_state,Data,[{reply,From,Data}]};
    -handle_event(_, _, Data) ->
    +    {keep_state,Data,[{reply,From,Data}]};
    +handle_event(_, _, Data) ->
         %% Ignore all other events
    -    {keep_state,Data}.

    The following is a shell session when running it:

    1> pushbutton:start().
    -{ok,<0.36.0>}
    -2> pushbutton:get_count().
    +    {keep_state,Data}.

    The following is a shell session when running it:

    1> pushbutton:start().
    +{ok,<0.36.0>}
    +2> pushbutton:get_count().
     0
    -3> pushbutton:push().
    +3> pushbutton:push().
     on
    -4> pushbutton:get_count().
    +4> pushbutton:get_count().
     1
    -5> pushbutton:push().
    +5> pushbutton:push().
     off
    -6> pushbutton:get_count().
    +6> pushbutton:get_count().
     1
    -7> pushbutton:stop().
    +7> pushbutton:stop().
     ok
    -8> pushbutton:push().
    +8> pushbutton:push().
     ** exception exit: {noproc,{gen_statem,call,[pushbutton_statem,push,infinity]}}
          in function  gen:do_for_proc/2 (gen.erl, line 261)
          in call from gen_statem:call/3 (gen_statem.erl, line 386)

    To compare styles, here follows the same example using callback mode handle_event_function, or rather, the code to replace after function init/1 -of the pushbutton.erl example file above:

    callback_mode() -> handle_event_function.
    +of the pushbutton.erl example file above:

    callback_mode() -> handle_event_function.
     
     %%% state callback(s)
     
    -handle_event({call,From}, push, off, Data) ->
    +handle_event({call,From}, push, off, Data) ->
         %% Go to 'on', increment count and reply
         %% that the resulting status is 'on'
    -    {next_state,on,Data+1,[{reply,From,on}]};
    -handle_event({call,From}, push, on, Data) ->
    +    {next_state,on,Data+1,[{reply,From,on}]};
    +handle_event({call,From}, push, on, Data) ->
         %% Go to 'off' and reply that the resulting status is 'off'
    -    {next_state,off,Data,[{reply,From,off}]};
    +    {next_state,off,Data,[{reply,From,off}]};
     %%
     %% Event handling common to all states
    -handle_event({call,From}, get_count, State, Data) ->
    +handle_event({call,From}, get_count, State, Data) ->
         %% Reply with the current count
    -    {next_state,State,Data,[{reply,From,Data}]};
    -handle_event(_, _, State, Data) ->
    +    {next_state,State,Data,[{reply,From,Data}]};
    +handle_event(_, _, State, Data) ->
         %% Ignore all other events
    -    {next_state,State,Data}.

    Note

    API changes

    • This behavior appeared in Erlang/OTP 19.0 as experimental.
    • In OTP 19.1 a backwards incompatible change of the return tuple from + {next_state,State,Data}.

    Note

    API changes

    • This behavior appeared in Erlang/OTP 19.0 as experimental.
    • In OTP 19.1 a backwards incompatible change of the return tuple from Module:init/1 was made, the mandatory callback function Module:callback_mode/0 was introduced, @@ -3112,15 +3112,15 @@ containing the same keys as the input map, but it may transform some values.

      One use case for this function is to return compact alternative state representations to avoid having large state terms printed in log files. -Another is to hide sensitive data from being written to the error log.

      Example:

      format_status(Status) ->
      -  maps:map(
      -    fun(state,State) ->
      -            maps:remove(private_key, State);
      -       (message,{password, _Pass}) ->
      -            {password, removed};
      -       (_,Value) ->
      +Another is to hide sensitive data from being written to the error log.

      Example:

      format_status(Status) ->
      +  maps:map(
      +    fun(state,State) ->
      +            maps:remove(private_key, State);
      +       (message,{password, _Pass}) ->
      +            {password, removed};
      +       (_,Value) ->
                   Value
      -    end, Status).

      Note

      This callback is optional, so a callback module does not need + end, Status).

      Note

      This callback is optional, so a callback module does not need to export it. The gen_statem module provides a default implementation of this function that returns {State, Data}.

      If this callback is exported but fails, to hide possibly sensitive data, the default function will instead return {State, Info}, @@ -3294,8 +3294,8 @@ to initialize the implementation state and server data.

      Args is the Args argument provided to that start function.

      Note

      Note that if the gen_statem is started through proc_lib and enter_loop/4,5,6, this callback will never be called. Since this callback is not optional -it can in that case be implemented as:

      -spec init(_) -> no_return().
      -init(Args) -> erlang:error(not_implemented, [Args]).
      +it can in that case be implemented as:

      -spec init(_) -> no_return().
      +init(Args) -> erlang:error(not_implemented, [Args]).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (876)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io.html 2026-08-21 04:00:29.456360072 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io.html 2026-08-21 04:00:29.458360085 +0000 @@ -107,7 +107,7 @@ binaries instead of lists. The binaries are encoded in UTF-8.

    To work with binaries in ISO Latin-1 encoding, use the file module instead.

    For conversion functions between character encodings, see the unicode module.

    Error Information

    The ErrorInfo mentioned in this module is the standard ErrorInfo structure -that is returned from all I/O modules. It has the following format:

    {ErrorLocation, Module, ErrorDescriptor}

    A string that describes the error is obtained with the following call:

    Module:format_error(ErrorDescriptor)
    +that is returned from all I/O modules. It has the following format:

    {ErrorLocation, Module, ErrorDescriptor}

    A string that describes the error is obtained with the following call:

    Module:format_error(ErrorDescriptor)
    @@ -1159,12 +1159,12 @@ no IoDevice argument is specified in the function calls in this module.

    It is sometimes desirable to use an explicit IoDevice argument that refers to the default I/O device. This is the case with functions that can access either a file or the default I/O device. The atom standard_io has this -special meaning. The following example illustrates this:

    27> io:read('enter>').
    +special meaning. The following example illustrates this:

    27> io:read('enter>').
     enter>foo.
    -{ok,foo}
    -28> io:read(standard_io, 'enter>').
    +{ok,foo}
    +28> io:read(standard_io, 'enter>').
     enter>bar.
    -{ok,bar}

    By default all I/O sent to standard_io will end up in the user +{ok,bar}

    By default all I/O sent to standard_io will end up in the user I/O device of the node that spawned the calling process.

    standard_io is an alias for group_leader/0, so in order to change where the default input/output requests are sent you can change the group leader of the current process using @@ -1439,33 +1439,33 @@ whitespace characters are stripped. An Erlang string (list of characters) is returned.

    If Unicode translation is in effect (~ts), characters > 255 are accepted, otherwise not. With the translation modifier, the returned list can as a -consequence also contain integers > 255:

    1> io:fread("Prompt> ","~s").
    +consequence also contain integers > 255:

    1> io:fread("Prompt> ","~s").
     Prompt> <Characters beyond latin1 range not printable in this medium>
    -{error,{fread,string}}
    -2> io:fread("Prompt> ","~ts").
    +{error,{fread,string}}
    +2> io:fread("Prompt> ","~ts").
     Prompt> <Characters beyond latin1 range not printable in this medium>
    -{ok,[[1091,1085,1080,1094,1086,1076,1077]]}
  • a - Similar to s, but the resulting string is converted into an +{ok,[[1091,1085,1080,1094,1086,1076,1077]]}

  • a - Similar to s, but the resulting string is converted into an atom.

  • c - The number of characters equal to the field width are read (default is 1) and returned as an Erlang string. However, leading and trailing whitespace characters are not omitted as they are with s. All -characters are returned.

    The Unicode translation modifier works as with s:

    1> io:fread("Prompt> ","~c").
    +characters are returned.

    The Unicode translation modifier works as with s:

    1> io:fread("Prompt> ","~c").
     Prompt> <Character beyond latin1 range not printable in this medium>
    -{error,{fread,string}}
    -2> io:fread("Prompt> ","~tc").
    +{error,{fread,string}}
    +2> io:fread("Prompt> ","~tc").
     Prompt> <Character beyond latin1 range not printable in this medium>
    -{ok,[[1091]]}
  • l - Returns the number of characters that have been scanned up to that +{ok,[[1091]]}

  • l - Returns the number of characters that have been scanned up to that point, including whitespace characters.

  • The function returns:
    • {ok, Terms} - The read was successful and Terms is the list of successfully matched and read items.

    • eof - End of file was encountered.

    • {error, FreadError} - The reading failed and FreadError gives a hint about the error.

    • {error, ErrorDescription} - The read operation failed and parameter -ErrorDescription gives a hint about the error.

    Examples:

    20> io:fread('enter>', "~f~f~f").
    +ErrorDescription gives a hint about the error.

    Examples:

    20> io:fread('enter>', "~f~f~f").
     enter>1.9 35.5e3 15.0
    -{ok,[1.9,3.55e4,15.0]}
    -21> io:fread('enter>', "~10f~d").
    +{ok,[1.9,3.55e4,15.0]}
    +21> io:fread('enter>', "~10f~d").
     enter>     5.67899
    -{ok,[5.678,99]}
    -22> io:fread('enter>', ":~10s:~10c:").
    +{ok,[5.678,99]}
    +22> io:fread('enter>', ":~10s:~10c:").
     enter>:   alan   :   joe    :
    -{ok, ["alan", "   joe    "]}
    +
    {ok, ["alan", " joe "]}
    @@ -1554,7 +1554,7 @@ the output device, and control sequences for formatting, see below. If Format is an atom or a binary, it is first converted to a list with the aid of atom_to_list/1 or -binary_to_list/1. Example:

    1> io:fwrite("Hello world!~n", []).
    +binary_to_list/1. Example:

    1> io:fwrite("Hello world!~n", []).
     Hello world!
     ok

    The general format of a control sequence is ~F.P.PadModC.

    The character C determines the type of control sequence to be used. It is the only required field. All of F, P, Pad, and Mod are optional. For @@ -1572,25 +1572,25 @@ padding character is ' ' (space).

  • Mod is the control sequence modifier. This is one or more characters that change the interpretation of Data.

    The current modifiers are:

    • t - For Unicode translation.

    • l - For stopping p and P from detecting printable characters.

    • k - For use with p, P, w, and W to format maps in map-key ordered order (see maps:iterator_order/0).

    • K - Similar to k, for formatting maps in map-key order, but takes an -extra argument that specifies the maps:iterator_order/0.

      For example:

      > M = #{ a => 1, b => 2 }.
      -#{a => 1,b => 2}
      -> io:format("~Kp~n", [reversed, M]).
      -#{b => 2,a => 1}
      +extra argument that specifies the maps:iterator_order/0.

      For example:

      > M = #{ a => 1, b => 2 }.
      +#{a => 1,b => 2}
      +> io:format("~Kp~n", [reversed, M]).
      +#{b => 2,a => 1}
       ok
  • If F, P, or Pad is a * character, the next argument in Data is used as -the value. For example:

    1> io:fwrite("~*.*.0f~n",[9, 5, 3.14159265]).
    +the value. For example:

    1> io:fwrite("~*.*.0f~n",[9, 5, 3.14159265]).
     003.14159
    -ok

    To use a literal * character as Pad, it must be passed as an argument:

    2> io:fwrite("~*.*.*f~n",[9, 5, $*, 3.14159265]).
    +ok

    To use a literal * character as Pad, it must be passed as an argument:

    2> io:fwrite("~*.*.*f~n",[9, 5, $*, 3.14159265]).
     **3.14159
     ok

    Available control sequences:

    • ~ - Character ~ is written.

    • c - The argument is a number that is interpreted as an ASCII code. The precision is the number of times the character is printed and defaults to the -field width, which in turn defaults to 1. Example:

      1> io:fwrite("|~10.5c|~-10.5c|~5c|~n", [$a, $b, $c]).
      +field width, which in turn defaults to 1. Example:

      1> io:fwrite("|~10.5c|~-10.5c|~5c|~n", [$a, $b, $c]).
       |     aaaaa|bbbbb     |ccccc|
       ok

      If the Unicode translation modifier (t) is in effect, the integer argument can be any number representing a valid Unicode codepoint, otherwise it is to -be an integer less than or equal to 255, otherwise it is masked with 16#FF:

      2> io:fwrite("~tc~n",[1024]).
      -\x{400}
      +be an integer less than or equal to 255, otherwise it is masked with 16#FF:

      2> io:fwrite("~tc~n",[1024]).
      +\x{400}
       ok
      -3> io:fwrite("~c~n",[1024]).
      +3> io:fwrite("~c~n",[1024]).
       ^@
       ok
    • f - The argument is a float that is written as [-]ddd.ddd, where the precision is the number of digits after the decimal point. The default @@ -1608,18 +1608,18 @@ binaries are in UTF-8. The characters are printed without quotes. The string is first truncated by the specified precision and then padded and justified to the specified field width. The default precision is the field width.

      This format can be used for printing any object and truncating the output so -it fits a specified field:

      1> io:fwrite("|~10w|~n", [{hey, hey, hey}]).
      +it fits a specified field:

      1> io:fwrite("|~10w|~n", [{hey, hey, hey}]).
       |**********|
       ok
      -2> io:fwrite("|~10s|~n", [io_lib:write({hey, hey, hey})]).
      -|{hey,hey,h|
      -3> io:fwrite("|~-10.8s|~n", [io_lib:write({hey, hey, hey})]).
      -|{hey,hey  |
      +2> io:fwrite("|~10s|~n", [io_lib:write({hey, hey, hey})]).
      +|{hey,hey,h|
      +3> io:fwrite("|~-10.8s|~n", [io_lib:write({hey, hey, hey})]).
      +|{hey,hey  |
       ok

      A list with integers > 255 is considered an error if the Unicode translation -modifier is not specified:

      4> io:fwrite("~ts~n",[[1024]]).
      -\x{400}
      +modifier is not specified:

      4> io:fwrite("~ts~n",[[1024]]).
      +\x{400}
       ok
      -5> io:fwrite("~s~n",[[1024]]).
      +5> io:fwrite("~s~n",[[1024]]).
       ** exception error: bad argument
            in function  io:format/3
               called as io:format(<0.53.0>,"~s~n",[[1024]])
    • w - Writes data with the standard syntax. This is used to output Erlang @@ -1630,122 +1630,122 @@ breaks terms whose printed representation is longer than one line into many lines and indents each line sensibly. Left-justification is not supported. It also tries to detect flat lists of printable characters and output these as -strings. For example:

      1> T = [{attributes,[[{id,age,1.50000},{mode,explicit},
      -{typename,"INTEGER"}], [{id,cho},{mode,explicit},{typename,'Cho'}]]},
      -{typename,'Person'},{tag,{'PRIVATE',3}},{mode,implicit}].
      +strings. For example:

      1> T = [{attributes,[[{id,age,1.50000},{mode,explicit},
      +{typename,"INTEGER"}], [{id,cho},{mode,explicit},{typename,'Cho'}]]},
      +{typename,'Person'},{tag,{'PRIVATE',3}},{mode,implicit}].
       ...
      -2> io:fwrite("~w~n", [T]).
      -[{attributes,[[{id,age,1.5},{mode,explicit},{typename,
      -[73,78,84,69,71,69,82]}],[{id,cho},{mode,explicit},{typena
      -me,'Cho'}]]},{typename,'Person'},{tag,{'PRIVATE',3}},{mode
      -,implicit}]
      +2> io:fwrite("~w~n", [T]).
      +[{attributes,[[{id,age,1.5},{mode,explicit},{typename,
      +[73,78,84,69,71,69,82]}],[{id,cho},{mode,explicit},{typena
      +me,'Cho'}]]},{typename,'Person'},{tag,{'PRIVATE',3}},{mode
      +,implicit}]
       ok
      -3> io:fwrite("~62p~n", [T]).
      -[{attributes,[[{id,age,1.5},
      -               {mode,explicit},
      -               {typename,"INTEGER"}],
      -              [{id,cho},{mode,explicit},{typename,'Cho'}]]},
      - {typename,'Person'},
      - {tag,{'PRIVATE',3}},
      - {mode,implicit}]
      +3> io:fwrite("~62p~n", [T]).
      +[{attributes,[[{id,age,1.5},
      +               {mode,explicit},
      +               {typename,"INTEGER"}],
      +              [{id,cho},{mode,explicit},{typename,'Cho'}]]},
      + {typename,'Person'},
      + {tag,{'PRIVATE',3}},
      + {mode,implicit}]
       ok

      The field width specifies the maximum line length. It defaults to 80. The precision specifies the initial indentation of the term. It defaults to the number of characters printed on this line in the same call to write/1 or -format/1,2,3. For example, using T above:

      4> io:fwrite("Here T = ~62p~n", [T]).
      -Here T = [{attributes,[[{id,age,1.5},
      -                        {mode,explicit},
      -                        {typename,"INTEGER"}],
      -                       [{id,cho},
      -                        {mode,explicit},
      -                        {typename,'Cho'}]]},
      -          {typename,'Person'},
      -          {tag,{'PRIVATE',3}},
      -          {mode,implicit}]
      +format/1,2,3. For example, using T above:

      4> io:fwrite("Here T = ~62p~n", [T]).
      /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io_lib.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (824))
      --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io_lib.html	2026-08-21 04:00:29.490360293 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io_lib.html	2026-08-21 04:00:29.490360293 +0000
      @@ -1263,8 +1263,8 @@
       input is needed to complete the original format string. RestFormat is the
       remaining format string, Nchars is the number of characters scanned, and
       InputStack is the reversed list of inputs matched up to that point.

    • {error, What} - The read operation failed and parameter What gives a -hint about the error.

    Example:

    3> io_lib:fread("~f~f~f", "15.6 17.3e-6 24.5").
    -{ok,[15.6,1.73e-5,24.5],[]}
    +hint about the error.

    Example:

    3> io_lib:fread("~f~f~f", "15.6 17.3e-6 24.5").
    +{ok,[15.6,1.73e-5,24.5],[]}
    @@ -1773,11 +1773,11 @@ "...".

    Depth defaults to -1, which means no limitation. Option CharsLimit puts a soft limit on the number of characters returned. When the number of characters is reached, remaining structures are replaced by "...". CharsLimit defaults to -1, -which means no limit on the number of characters returned.

    Example:

    1> lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9})).
    +which means no limit on the number of characters returned.

    Example:

    1> lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9})).
     "{1,[2],[3],[4,5],6,7,8,9}"
    -2> lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9}, 5)).
    +2> lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9}, 5)).
     "{1,[2],[3],[...],...}"
    -3> lists:flatten(io_lib:write({[1,2,3],[4,5],6,7,8,9}, [{chars_limit,20}])).
    +3> lists:flatten(io_lib:write({[1,2,3],[4,5],6,7,8,9}, [{chars_limit,20}])).
     "{[1,2|...],[4|...],...}"
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io_protocol.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1563)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io_protocol.html 2026-08-21 04:00:29.519360482 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/io_protocol.html 2026-08-21 04:00:29.519360482 +0000 @@ -104,8 +104,8 @@ ever present in the client. Any I/O server can be used together with any client code, and the client code does not need to be aware of the I/O device that the I/O server communicates with.

    Protocol Basics

    As described in Robert's paper, I/O servers and clients communicate using -io_request/io_reply tuples as follows:

    {io_request, From, ReplyAs, Request}
    -{io_reply, ReplyAs, Reply}

    The client sends an io_request tuple to the I/O server and the server +io_request/io_reply tuples as follows:

    {io_request, From, ReplyAs, Request}
    +{io_reply, ReplyAs, Reply}

    The client sends an io_request tuple to the I/O server and the server eventually sends a corresponding io_reply tuple.

    • From is the pid/0 of the client, the process which the I/O server sends the I/O reply to.

    • ReplyAs can be any datum and is returned in the corresponding io_reply. The io module monitors the I/O server and uses the monitor reference as @@ -116,8 +116,8 @@ io_reply. The reply can be sent from any process, not necessarily the actual I/O server.

    • Request and Reply are described below.

    When an I/O server receives an io_request tuple, it acts upon the Request part and eventually sends an io_reply tuple with the corresponding Reply -part.

    Output Requests

    To output characters on an I/O device, the following Requests exist:

    {put_chars, Encoding, Characters}
    -{put_chars, Encoding, Module, Function, Args}
    • Encoding is unicode or latin1, meaning that the characters are (in case +part.

      Output Requests

      To output characters on an I/O device, the following Requests exist:

      {put_chars, Encoding, Characters}
      +{put_chars, Encoding, Module, Function, Args}
      • Encoding is unicode or latin1, meaning that the characters are (in case of binaries) encoded as UTF-8 or ISO Latin-1 (pure bytes). A well-behaved I/O server is also to return an error indication if list elements contain integers > 255 when Encoding is set to latin1.

        Notice that this does not in any way tell how characters are to be put on the @@ -136,8 +136,8 @@ the function returns anything else than a binary or list, or throws an exception, an error is to be sent back to the client.

      The I/O server replies to the client with an io_reply tuple, where element Reply is one of:

      ok
      -{error, Error}
      • Error describes the error to the client, which can do whatever it wants with -it. The io module typically returns it "as is".

      Input Requests

      To read characters from an I/O device, the following Requests exist:

      {get_until, Encoding, Prompt, Module, Function, ExtraArgs}
      • Encoding denotes how data is to be sent back to the client and what data is +{error, Error}

    • Error describes the error to the client, which can do whatever it wants with +it. The io module typically returns it "as is".

    Input Requests

    To read characters from an I/O device, the following Requests exist:

    {get_until, Encoding, Prompt, Module, Function, ExtraArgs}
    • Encoding denotes how data is to be sent back to the client and what data is sent to the function denoted by Module/Function/ExtraArgs. If the function supplied returns data as a list, the data is converted to this encoding. If the function supplied returns data in some other format, no @@ -153,8 +153,8 @@ nothing being written to the I/O device).

    • Module, Function, and ExtraArgs denote a function and arguments to determine when enough data is written. The function is to take two more arguments, the last state, and a list of characters. The function is to return -one of:

      {done, Result, RestChars}
      -{more, Continuation}

      Result can be any Erlang term, but if it is a list/0, the I/O server can +one of:

      {done, Result, RestChars}
      +{more, Continuation}

      Result can be any Erlang term, but if it is a list/0, the I/O server can convert it to a binary/0 of appropriate format before returning it to the client, if the I/O server is set in binary mode (see below).

      The function is called with the data the I/O server finds on its I/O device, returning one of:

      • {done, Result, RestChars} when enough data is read. In this case Result @@ -164,38 +164,38 @@ characters are available. When no more characters are available, the function must return {done, eof, Rest}. The initial state is the empty list. The data when an end of file is reached on the IO device is the atom eof.

        An emulation of the get_line request can be (inefficiently) implemented -using the following functions:

        -module(demo).
        --export([until_newline/3, get_line/1]).
        +using the following functions:

        -module(demo).
        +-export([until_newline/3, get_line/1]).
         
        -until_newline(_ThisFar,eof,_MyStopCharacter) ->
        -    {done,eof,[]};
        -until_newline(ThisFar,CharList,MyStopCharacter) ->
        +until_newline(_ThisFar,eof,_MyStopCharacter) ->
        +    {done,eof,[]};
        +until_newline(ThisFar,CharList,MyStopCharacter) ->
             case
        -        lists:splitwith(fun(X) -> X =/= MyStopCharacter end,  CharList)
        +        lists:splitwith(fun(X) -> X =/= MyStopCharacter end,  CharList)
             of
        -  {L,[]} ->
        -            {more,ThisFar++L};
        -  {L2,[MyStopCharacter|Rest]} ->
        -      {done,ThisFar++L2++[MyStopCharacter],Rest}
        +  {L,[]} ->
        +            {more,ThisFar++L};
        +  {L2,[MyStopCharacter|Rest]} ->
        +      {done,ThisFar++L2++[MyStopCharacter],Rest}
             end.
         
        -get_line(IoServer) ->
        -    IoServer ! {io_request,
        -                self(),
        +get_line(IoServer) ->
        +    IoServer ! {io_request,
        +                self(),
                         IoServer,
        -                {get_until, unicode, '', ?MODULE, until_newline, [$\n]}},
        +                {get_until, unicode, '', ?MODULE, until_newline, [$\n]}},
             receive
        -        {io_reply, IoServer, Data} ->
        +        {io_reply, IoServer, Data} ->
               Data
             end.

        Notice that the last element in the Request tuple ([$\n]) is appended to the argument list when the function is called. The function is to be called like apply(Module, Function, [ State, Data | ExtraArgs ]) by -the I/O server.

      A fixed number of characters is requested using the following Request:

      {get_chars, Encoding, Prompt, N}
      • Encoding and Prompt as for get_until.
      • N is the number of characters to be read from the I/O device.

      A single line (as in former example) is requested with the following Request:

      {get_line, Encoding, Prompt}
      • Encoding and Prompt as for get_until.

      Clearly, get_chars and get_line could be implemented with the get_until +the I/O server.

    A fixed number of characters is requested using the following Request:

    {get_chars, Encoding, Prompt, N}
    • Encoding and Prompt as for get_until.
    • N is the number of characters to be read from the I/O device.

    A single line (as in former example) is requested with the following Request:

    {get_line, Encoding, Prompt}
    • Encoding and Prompt as for get_until.

    Clearly, get_chars and get_line could be implemented with the get_until request (and indeed they were originally), but demands for efficiency have made these additions necessary.

    The I/O server replies to the client with an io_reply tuple, where element Reply is one of:

    Data
     eof
    -{error, Error}
    • Data is the characters read, in list or binary form (depending on the I/O +{error, Error}
    • Data is the characters read, in list or binary form (depending on the I/O server mode, see the next section).
    • eof is returned when input end is reached and no more data is available to the client process.
    • Error describes the error to the client, which can do whatever it wants with it. The io module typically returns it as is.

    I/O Server Modes

    Demands for efficiency when reading data from an I/O server has not only lead to @@ -215,164 +215,164 @@ This is done in the example in section An Annotated and Working Example I/O Server.

    An I/O server in binary mode affects the data sent to the client, so that it must be able to handle binary data. For convenience, the modes of an I/O server -can be set and retrieved using the following I/O requests:

    {setopts, Opts}
    • Opts is a list of options in the format recognized by the proplists +can be set and retrieved using the following I/O requests:

      {setopts, Opts}
      • Opts is a list of options in the format recognized by the proplists module (and by the I/O server).

      As an example, the I/O server for the interactive shell (in group.erl) -understands the following options:

      {binary, boolean()} (or binary/list)
      -{echo, boolean()}
      -{expand_fun, fun()}
      -{encoding, unicode/latin1} (or unicode/latin1)

      Options binary and encoding are common for all I/O servers in OTP, while +understands the following options:

      {binary, boolean()} (or binary/list)
      +{echo, boolean()}
      +{expand_fun, fun()}
      +{encoding, unicode/latin1} (or unicode/latin1)

      Options binary and encoding are common for all I/O servers in OTP, while echo and expand are valid only for this I/O server. Option unicode notifies how characters are put on the physical I/O device, that is, if the terminal itself is Unicode-aware. It does not affect how characters are sent in the I/O protocol, where each request contains encoding information for the provided or returned data.

      The I/O server is to send one of the following as Reply:

      ok
      -{error, Error}

      An error (preferably enotsup) is to be expected if the option is not supported +{error, Error}

    An error (preferably enotsup) is to be expected if the option is not supported by the I/O server (like if an echo option is sent in a setopts request to a plain file).

    To retrieve options, the following request is used:

    getopts

    This request asks for a complete list of all options supported by the I/O server as well as their current values.

    The I/O server replies:

    OptList
    -{error, Error}
    • OptList is a list of tuples {Option, Value}, where Option always is an +{error, Error}
    • OptList is a list of tuples {Option, Value}, where Option always is an atom.

    Multiple I/O Requests

    The Request element can in itself contain many Requests by using the -following format:

    {requests, Requests}
    • Requests is a list of valid io_request tuples for the protocol. They must +following format:

      {requests, Requests}
      • Requests is a list of valid io_request tuples for the protocol. They must be executed in the order that they appear in the list. The execution is to continue until one of the requests results in an error or the list is consumed. The result of the last request is sent back to the client.

      The I/O server can, for a list of requests, send any of the following valid results in the reply, depending on the requests in the list:

      ok
      -{ok, Data}
      -{ok, Options}
      -{error, Error}

      Optional I/O Request

      The following I/O request is optional to implement and a client is to be -prepared for an error return:

      {get_geometry, Geometry}
      • Geometry is the atom rows or the atom columns.

      The I/O server is to send one of the following as Reply:

      N
      -{error, Error}
      • N is the number of character rows or columns that the I/O device has, if +{ok, Data} +{ok, Options} +{error, Error}

    Optional I/O Request

    The following I/O request is optional to implement and a client is to be +prepared for an error return:

    {get_geometry, Geometry}
    • Geometry is the atom rows or the atom columns.

    The I/O server is to send one of the following as Reply:

    N
    +{error, Error}
    • N is the number of character rows or columns that the I/O device has, if applicable to the I/O device handled by the I/O server, otherwise {error, enotsup} is a good answer.

    Unimplemented Request Types

    If an I/O server encounters a request that it does not recognize (that is, the io_request tuple has the expected format, but the Request is unknown), the -I/O server is to send a valid reply with the error tuple:

    {error, request}

    This makes it possible to extend the protocol with optional requests and for the +I/O server is to send a valid reply with the error tuple:

    {error, request}

    This makes it possible to extend the protocol with optional requests and for the clients to be somewhat backward compatible.

    An Annotated and Working Example I/O Server

    An I/O server is any process capable of handling the I/O protocol. There is no generic I/O server behavior, but could well be. The framework is simple, a process handling incoming requests, usually both I/O-requests and other I/O device-specific requests (positioning, closing, and so on).

    The example I/O server stores characters in an ETS table, making up a fairly crude RAM file.

    The module begins with the usual directives, a function to start the I/O server -and a main loop handling the requests:

    -module(ets_io_server).
    +and a main loop handling the requests:

    -module(ets_io_server).
     
    --export([start_link/0, init/0, loop/1, until_newline/3, until_enough/3]).
    +-export([start_link/0, init/0, loop/1, until_newline/3, until_enough/3]).
     
    --define(CHARS_PER_REC, 10).
    +-define(CHARS_PER_REC, 10).
     
    --record(state, {
    +-record(state, {
     	  table,
     	  position, % absolute
     	  mode % binary | list
    -	 }).
    +	 }).
     
    -start_link() ->
    -    spawn_link(?MODULE,init,[]).
    +start_link() ->
    +    spawn_link(?MODULE,init,[]).
     
    -init() ->
    -    Table = ets:new(noname,[ordered_set]),
    -    ?MODULE:loop(#href_anchor"ss">state{table = Table, position = 0, mode=list}).
    +init() ->
    +    Table = ets:new(noname,[ordered_set]),
    +    ?MODULE:loop(#href_anchor"ss">state{table = Table, position = 0, mode=list}).
     
    -loop(State) ->
    +loop(State) ->
         receive
    -	{io_request, From, ReplyAs, Request} ->
    -	    case request(Request,State) of
    -		{Tag, Reply, NewState} when Tag =:= ok; Tag =:= error ->
    -		    reply(From, ReplyAs, Reply),
    -		    ?MODULE:loop(NewState);
    -		{stop, Reply, _NewState} ->
    -		    reply(From, ReplyAs, Reply),
    -		    exit(Reply)
    +	{io_request, From, ReplyAs, Request} ->
    +	    case request(Request,State) of
    +		{Tag, Reply, NewState} when Tag =:= ok; Tag =:= error ->
    +		    reply(From, ReplyAs, Reply),
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/json.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (3323))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/json.html	2026-08-21 04:00:29.552360697 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/json.html	2026-08-21 04:00:29.552360697 +0000
    @@ -964,8 +964,8 @@
     
           
     
    -

    Parses a JSON value from Binary.

    Supports basic data mapping:

    JSONErlang
    Numberinteger() | float()
    Booleantrue | false
    Nullnull
    Stringbinary()
    Object#{binary() => _}

    Errors

    • error(unexpected_end) if Binary contains incomplete JSON value
    • error({invalid_byte, Byte}) if Binary contains unexpected byte or invalid UTF-8 byte
    • error({unexpected_sequence, Bytes}) if Binary contains invalid UTF-8 escape

    Example

    > json:decode(<<"{\"foo\": 1}">>).
    -#{<<"foo">> => 1}
    +

    Parses a JSON value from Binary.

    Supports basic data mapping:

    JSONErlang
    Numberinteger() | float()
    Booleantrue | false
    Nullnull
    Stringbinary()
    Object#{binary() => _}

    Errors

    • error(unexpected_end) if Binary contains incomplete JSON value
    • error({invalid_byte, Byte}) if Binary contains unexpected byte or invalid UTF-8 byte
    • error({unexpected_sequence, Bytes}) if Binary contains invalid UTF-8 escape

    Example

    > json:decode(<<"{\"foo\": 1}">>).
    +#{<<"foo">> => 1}
    @@ -999,9 +999,9 @@ can be customized with the callbacks specified in Decoders. The callbacks will use the Acc value as the initial accumulator.

    Any leftover, unparsed data in Binary will be returned.

    Default callbacks

    All callbacks are optional. If not provided, they will fall back to -implementations used by the decode/1 function:

    • for array_start: fun(_) -> [] end
    • for array_push: fun(Elem, Acc) -> [Elem | Acc] end

    • for array_finish: fun(Acc, OldAcc) -> {lists:reverse(Acc), OldAcc} end
    • for object_start: fun(_) -> [] end
    • for object_push: fun(Key, Value, Acc) -> [{Key, Value} | Acc] end

    • for object_finish: fun(Acc, OldAcc) -> {maps:from_list(Acc), OldAcc} end
    • for float: fun erlang:binary_to_float/1
    • for integer: fun erlang:binary_to_integer/1
    • for string: fun (Value) -> Value end
    • for null: the atom null

    Errors

    • error({invalid_byte, Byte}) if Binary contains unexpected byte or invalid UTF-8 byte
    • error({unexpected_sequence, Bytes}) if Binary contains invalid UTF-8 escape
    • error(unexpected_end) if Binary contains incomplete JSON value

    Example

    Decoding object keys as atoms:

    > Push = fun(Key, Value, Acc) -> [{binary_to_existing_atom(Key), Value} | Acc] end.
    -> json:decode(<<"{\"foo\": 1}">>, ok, #{object_push => Push}).
    -{#{foo => 1},ok,<<>>}
    +implementations used by the decode/1 function:

    • for array_start: fun(_) -> [] end
    • for array_push: fun(Elem, Acc) -> [Elem | Acc] end

    • for array_finish: fun(Acc, OldAcc) -> {lists:reverse(Acc), OldAcc} end
    • for object_start: fun(_) -> [] end
    • for object_push: fun(Key, Value, Acc) -> [{Key, Value} | Acc] end

    • for object_finish: fun(Acc, OldAcc) -> {maps:from_list(Acc), OldAcc} end
    • for float: fun erlang:binary_to_float/1
    • for integer: fun erlang:binary_to_integer/1
    • for string: fun (Value) -> Value end
    • for null: the atom null

    Errors

    • error({invalid_byte, Byte}) if Binary contains unexpected byte or invalid UTF-8 byte
    • error({unexpected_sequence, Bytes}) if Binary contains invalid UTF-8 escape
    • error(unexpected_end) if Binary contains incomplete JSON value

    Example

    Decoding object keys as atoms:

    > Push = fun(Key, Value, Acc) -> [{binary_to_existing_atom(Key), Value} | Acc] end.
    +> json:decode(<<"{\"foo\": 1}">>, ok, #{object_push => Push}).
    +{#{foo => 1},ok,<<>>}
    @@ -1034,11 +1034,11 @@

    Continue parsing a stream of bytes of a JSON value.

    Similar to decode_start/3, if the function returns {continue, State} and -there is no more data, use end_of_input instead of a binary.

    > {continue, State} = json:decode_start(<<"{\"foo\":">>, ok, #{}).
    -> json:decode_continue(<<"1}">>, State).
    -{#{foo => 1},ok,<<>>}
    > {continue, State} = json:decode_start(<<"123">>, ok, #{}).
    -> json:decode_continue(end_of_input, State).
    -{123,ok,<<>>}
    +there is no more data, use end_of_input instead of a binary.

    > {continue, State} = json:decode_start(<<"{\"foo\":">>, ok, #{}).
    +> json:decode_continue(<<"1}">>, State).
    +{#{foo => 1},ok,<<>>}
    > {continue, State} = json:decode_start(<<"123">>, ok, #{}).
    +> json:decode_continue(end_of_input, State).
    +{123,ok,<<>>}
    @@ -1102,8 +1102,8 @@ -

    Generates JSON corresponding to Term.

    Supports basic data mapping:

    ErlangJSON
    integer() | float()Number
    true | falseBoolean
    nullNull
    binary()String
    atom()String
    list()Array
    #{binary() => _}Object
    #{atom() => _}Object
    #{integer() => _}Object

    This is equivalent to encode(Term, fun json:encode_value/2).

    Examples

    > iolist_to_binary(json:encode(#{foo => <<"bar">>})).
    -<<"{\"foo\":\"bar\"}">>
    +

    Generates JSON corresponding to Term.

    Supports basic data mapping:

    ErlangJSON
    integer() | float()Number
    true | falseBoolean
    nullNull
    binary()String
    atom()String
    list()Array
    #{binary() => _}Object
    #{atom() => _}Object
    #{integer() => _}Object

    This is equivalent to encode(Term, fun json:encode_value/2).

    Examples

    > iolist_to_binary(json:encode(#{foo => <<"bar">>})).
    +<<"{\"foo\":\"bar\"}">>
    @@ -1138,11 +1138,11 @@ to be encoded and is expected to return the corresponding encoded JSON as iodata.

    Various encode_* functions in this module can be used to help in constructing such callbacks.

    Examples

    An encoder that uses a heuristic to differentiate object-like -lists of key-value pairs from plain lists:

    > encoder([{_, _} | _] = Value, Encode) -> json:encode_key_value_list(Value, Encode);
    -> encoder(Other, Encode) -> json:encode_value(Other, Encode).
    -> custom_encode(Value) -> json:encode(Value, fun(Value, Encode) -> encoder(Value, Encode) end).
    -> iolist_to_binary(custom_encode([{a, []}, {b, 1}])).
    -<<"{\"a\":[],\"b\":1}">>
    +lists of key-value pairs from plain lists:

    > encoder([{_, _} | _] = Value, Encode) -> json:encode_key_value_list(Value, Encode);
    +> encoder(Other, Encode) -> json:encode_value(Other, Encode).
    +> custom_encode(Value) -> json:encode(Value, fun(Value, Encode) -> encoder(Value, Encode) end).
    +> iolist_to_binary(custom_encode([{a, []}, {b, 1}])).
    +<<"{\"a\":[],\"b\":1}">>
    @@ -1509,11 +1509,11 @@ -

    Generates formatted JSON corresponding to Term.

    Similiar to encode/1 but with added whitespaces for formatting.

    > io:put_chars(json:format(#{foo => <<"bar">>, baz => 52})).
    -{
    +

    Generates formatted JSON corresponding to Term.

    Similiar to encode/1 but with added whitespaces for formatting.

    > io:put_chars(json:format(#{foo => <<"bar">>, baz => 52})).
    +{
       "baz": 52,
       "foo": "bar"
    -}
    +}
     ok
    @@ -1578,20 +1578,20 @@

    Generates formatted JSON corresponding to Term.

    Similar to encode/2, can be customised with the Encoder callback and Options.

    Options can include 'indent' to specify number of spaces per level and 'max' which loosely limits the width of lists.

    The Encoder will get a 'State' argument which contains the 'Options' maps merged with other data when recursing through 'Term'.

    format_value/3 or various encode_* functions in this module can be used -to help in constructing such callbacks.

    > formatter({posix_time, SysTimeSecs}, Encode, State) ->
    -    TimeStr = calendar:system_time_to_rfc3339(SysTimeSecs, [{offset, "Z"}]),
    -    json:format_value(unicode:characters_to_binary(TimeStr), Encode, State);
    -> formatter(Other, Encode, State) -> json:format_value(Other, Encode, State).
    +to help in constructing such callbacks.

    > formatter({posix_time, SysTimeSecs}, Encode, State) ->
    +    TimeStr = calendar:system_time_to_rfc3339(SysTimeSecs, [{offset, "Z"}]),
    +    json:format_value(unicode:characters_to_binary(TimeStr), Encode, State);
    +> formatter(Other, Encode, State) -> json:format_value(Other, Encode, State).
     >
    -> Fun = fun(Value, Encode, State) -> formatter(Value, Encode, State) end.
    -> Options = #{indent => 4}.
    -> Term = #{id => 1, time => {posix_time, erlang:system_time(seconds)}}.
    +> Fun = fun(Value, Encode, State) -> formatter(Value, Encode, State) end.
    +> Options = #{indent => 4}.
    +> Term = #{id => 1, time => {posix_time, erlang:system_time(seconds)}}.
     >
    -> io:put_chars(json:format(Term, Fun, Options)).
    -{
    +> io:put_chars(json:format(Term, Fun, Options)).
    +{
         "id": 1,
         "time": "2024-05-23T16:07:48Z"
    -}
    +}
     ok
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/lists.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1570)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/lists.html 2026-08-21 04:00:29.613361094 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/lists.html 2026-08-21 04:00:29.612361087 +0000 @@ -1038,10 +1038,10 @@

    Returns true if Pred(Elem) returns true for all elements Elem in List; -otherwise, returns false.

    Examples

    1> IsEven = fun(N) -> N rem 2 =:= 0 end.
    -2> lists:all(IsEven, [2,4,5]).
    +otherwise, returns false.

    Examples

    1> IsEven = fun(N) -> N rem 2 =:= 0 end.
    +2> lists:all(IsEven, [2,4,5]).
     false
    -3> lists:all(IsEven, [2,4,6]).
    +3> lists:all(IsEven, [2,4,6]).
     true
    @@ -1071,10 +1071,10 @@

    Returns true if Pred(Elem) returns true for at least one element Elem in -List; otherwise, returns false.

    Examples

    1> IsEven = fun(N) -> N rem 2 =:= 0 end.
    -2> lists:any(IsEven, [3,5,7]).
    +List; otherwise, returns false.

    Examples

    1> IsEven = fun(N) -> N rem 2 =:= 0 end.
    +2> lists:any(IsEven, [3,5,7]).
     false
    -3> lists:any(IsEven, [2,3,5,7]).
    +3> lists:any(IsEven, [2,3,5,7]).
     true
    @@ -1103,8 +1103,8 @@ -

    Returns a list in which all sublists of ListOfLists have been concatenated.

    Examples

    1> lists:append([[1, 2, 3], [a, b], [4, 5, 6]]).
    -[1,2,3,a,b,4,5,6]
    +

    Returns a list in which all sublists of ListOfLists have been concatenated.

    Examples

    1> lists:append([[1, 2, 3], [a, b], [4, 5, 6]]).
    +[1,2,3,a,b,4,5,6]
    @@ -1133,7 +1133,7 @@

    Returns a new list, List3, consisting of the elements of -List1, followed by the elements of List2.

    Examples

    1> lists:append("abc", "def").
    +List1, followed by the elements of List2.

    Examples

    1> lists:append("abc", "def").
     "abcdef"

    lists:append(A, B) is equivalent to A ++ B.

    @@ -1163,7 +1163,7 @@ -

    Concatenates the text representation of the elements of Things.

    The elements of Things can be atoms, integers, floats, or strings.

    Examples

    1> lists:concat([doc, '/', file, '.', 3]).
    +

    Concatenates the text representation of the elements of Things.

    The elements of Things can be atoms, integers, floats, or strings.

    Examples

    1> lists:concat([doc, '/', file, '.', 3]).
     "doc/file.3"
    @@ -1193,10 +1193,10 @@

    Returns a copy of List1 where the first element matching Elem is removed, if -there is such an element.

    Examples

    1> lists:delete(b, [a,b,c]).
    -[a,c]
    -2> lists:delete(x, [a,b,c]).
    -[a,b,c]
    +there is such an element.

    Examples

    1> lists:delete(b, [a,b,c]).
    +[a,c]
    +2> lists:delete(x, [a,b,c]).
    +[a,b,c]
    @@ -1227,11 +1227,11 @@

    Drops the last element of a List.

    The list must be non-empty; otherwise, the function raises a -function_clause exception.

    Examples

    1> lists:droplast([1]).
    -[]
    -2> lists:droplast([1,2,3]).
    -[1,2]
    -3> lists:droplast([]).
    +function_clause exception.

    Examples

    1> lists:droplast([1]).
    +[]
    +2> lists:droplast([1,2,3]).
    +[1,2]
    +3> lists:droplast([]).
     ** exception error: no function clause matching lists:droplast([])
    @@ -1262,10 +1262,10 @@

    Drops elements Elem from List1 while Pred(Elem) returns true, -and then returns the remaining list.

    Examples

    1> lists:dropwhile(fun is_atom/1, [a,b,c,1,2,3,x,y,z]).
    -[1,2,3,x,y,z]
    -2> lists:dropwhile(fun is_integer/1, [a,b,c,1,2,3,x,y,z]).
    -[a,b,c,1,2,3,x,y,z]
    +and then returns the remaining list.

    Examples

    1> lists:dropwhile(fun is_atom/1, [a,b,c,1,2,3,x,y,z]).
    +[1,2,3,x,y,z]
    +2> lists:dropwhile(fun is_integer/1, [a,b,c,1,2,3,x,y,z]).
    +[a,b,c,1,2,3,x,y,z]
    @@ -1293,8 +1293,8 @@ -

    Returns a list containing N copies of term Elem.

    Examples

    1> lists:duplicate(5, xx).
    -[xx,xx,xx,xx,xx]
    +

    Returns a list containing N copies of term Elem.

    Examples

    1> lists:duplicate(5, xx).
    +[xx,xx,xx,xx,xx]
    @@ -1395,14 +1395,14 @@

    Returns List1 with each element H replaced by a tuple of form {I, H}, where I is the position of H in List1.

    The enumeration starts with Index and increases by Step in each step.

    That is, enumerate/3 behaves as if it were defined as -follows:

    enumerate(I, S, List) ->
    -  {List1, _ } = lists:mapfoldl(fun(T, Acc) -> {{Acc, T}, Acc+S} end, I, List),
    -  List1.

    The default values for Index and Step are both 1.

    Examples

    1> lists:enumerate([a,b,c]).
    -[{1,a},{2,b},{3,c}]
    -2> lists:enumerate(10, [a,b,c]).
    -[{10,a},{11,b},{12,c}]
    -3> lists:enumerate(0, -2, [a,b,c]).
    -[{0,a},{-2,b},{-4,c}]
    +follows:

    enumerate(I, S, List) ->
    +  {List1, _ } = lists:mapfoldl(fun(T, Acc) -> {{Acc, T}, Acc+S} end, I, List),
    +  List1.

    The default values for Index and Step are both 1.

    Examples

    1> lists:enumerate([a,b,c]).
    +[{1,a},{2,b},{3,c}]
    +2> lists:enumerate(10, [a,b,c]).
    +[{10,a},{11,b},{12,c}]
    +3> lists:enumerate(0, -2, [a,b,c]).
    +[{0,a},{-2,b},{-4,c}]
    @@ -1432,9 +1432,9 @@

    Returns a list of elements Elem in List1 for which Pred(Elem) -returns true.

    Examples

    1> IsEven = fun(N) -> N rem 2 =:= 0 end.
    -2> lists:filter(IsEven, [1,2,3,4,5]).
    -[2,4]
    +returns true.

    Examples

    1> IsEven = fun(N) -> N rem 2 =:= 0 end.
    +2> lists:filter(IsEven, [1,2,3,4,5]).
    +[2,4]
    @@ -1473,20 +1473,20 @@

    Calls Fun(Elem) on successive elements Elem of List1 to update or remove elements from List1.

    Fun/1 must return either a Boolean or a tuple {true, Value}. The function returns the list of elements for which Fun returns a new -value, with true being equivalent to {true, Elem}.

    That is, filtermap behaves as if it were defined as follows:

    filtermap(Fun, List1) ->
    -    lists:flatmap(fun(Elem) ->
    -                          case Fun(Elem) of
    -                              false -> [];
    -                              true -> [Elem];
    -                              {true,Value} -> [Value]
    +value, with true being equivalent to {true, Elem}.

    That is, filtermap behaves as if it were defined as follows:

    filtermap(Fun, List1) ->
    +    lists:flatmap(fun(Elem) ->
    +                          case Fun(Elem) of
    +                              false -> [];
    +                              true -> [Elem];
    +                              {true,Value} -> [Value]
                               end
    -                  end, List1).

    Examples

    1> lists:filtermap(fun(X) ->
    +                  end, List1).

    Examples

    1> lists:filtermap(fun(X) ->
                                case X rem 2 of
    -                               0 -> {true, X div 2};
    +                               0 -> {true, X div 2};
                                    1 -> false
                                end
    -                   end, [1,2,3,4,5]).
    -[1,2]
    +
    end, [1,2,3,4,5]). +[1,2]
    @@ -1514,9 +1514,9 @@ -

    Equivalent to length(flatten(DeepList)), but more efficient.

    Examples

    1> lists:flatlength([a,[b,c,[d,e]],f,[[g,h,i]]]).
    +

    Equivalent to length(flatten(DeepList)), but more efficient.

    Examples

    1> lists:flatlength([a,[b,c,[d,e]],f,[[g,h,i]]]).
     9
    -2> lists:flatlength([[[]]]).
    +2> lists:flatlength([[[]]]).
     0
    @@ -1548,14 +1548,14 @@

    Takes a function from As to lists of Bs, and a list of As (List1), producing a list of Bs by applying the function to each element in List1 and /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/maps.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1428)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/maps.html 2026-08-21 04:00:29.652361347 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/maps.html 2026-08-21 04:00:29.652361347 +0000 @@ -699,10 +699,10 @@

    Returns a map Map where each key-value pair from MapOrIter satisfies the predicate Pred(Key, Value).

    Unless MapOrIter is an ordered iterator returned by iterator/2, the order of the Pred(Key, Value) calls is not defined.

    The call fails with a {badmap,Map} exception if MapOrIter is not a map or -valid iterator, or with badarg if Pred is not a function of arity 2.

    Examples

    1> M = #{a => 2, b => 3, "a" => 1, "b" => 2}.
    -2> Pred = fun(K, V) -> is_atom(K) andalso V rem 2 =:= 0 end.
    -3> maps:filter(Pred, M).
    -#{a => 2}
    +valid iterator, or with badarg if Pred is not a function of arity 2.

    Examples

    1> M = #{a => 2, b => 3, "a" => 1, "b" => 2}.
    +2> Pred = fun(K, V) -> is_atom(K) andalso V rem 2 =:= 0 end.
    +3> maps:filter(Pred, M).
    +#{a => 2}
    @@ -742,12 +742,12 @@ {true, NewValue}, the value for Key is replaced with NewValue in the result map.

    Unless MapOrIter is an ordered iterator returned by iterator/2, the order of the Fun(Key, Value1) calls is not defined.

    The call fails with a {badmap,Map} exception if MapOrIter is not a map or -valid iterator, or with badarg if Fun is not a function of arity 2.

    Examples

    1> Fun = fun(K, V) when is_atom(K) -> {true, V*2};
    -            (_, V) -> V rem 2 =:= 0
    +valid iterator, or with badarg if Fun is not a function of arity 2.

    Examples

    1> Fun = fun(K, V) when is_atom(K) -> {true, V*2};
    +            (_, V) -> V rem 2 =:= 0
        end.
    -2> Map = #{k1 => 1, "k2" => 2, "k3" => 3}.
    -3> maps:filtermap(Fun, Map).
    -#{k1 => 2,"k2" => 2}
    +2>
    Map = #{k1 => 1, "k2" => 2, "k3" => 3}. +3> maps:filtermap(Fun, Map). +#{k1 => 2,"k2" => 2}
    @@ -778,10 +778,10 @@

    Returns a tuple {ok, Value}, where Value is the value associated with Key, -or error if no value is associated with Key in Map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Examples

    1> Map = #{"hi" => 42}.
    +or error if no value is associated with Key in Map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Examples

    1> Map = #{"hi" => 42}.
     2> Key = "hi".
    -3> maps:find(Key, Map).
    -{ok,42}
    +3>
    maps:find(Key, Map). +{ok,42}
    @@ -824,9 +824,9 @@ map is empty.

    Unless MapOrIter is an ordered iterator returned by iterator/2, the order of the Fun(Key, Value, AccIn) calls is not defined.

    The call fails with a {badmap,Map} exception if MapOrIter is not a map or valid iterator, or with badarg if Fun is not a function of -arity 3.

    Examples

    1> Fun = fun(K, V, AccIn) -> AccIn + V end.
    -2> Map = #{k1 => 1, k2 => 2, k3 => 3}.
    -3> maps:fold(Fun, 0, Map).
    +arity 3.

    Examples

    1> Fun = fun(K, V, AccIn) -> AccIn + V end.
    +2> Map = #{k1 => 1, k2 => 2, k3 => 3}.
    +3> maps:fold(Fun, 0, Map).
     6
    @@ -863,12 +863,12 @@

    Calls Fun(Key, Value) for every Key to Value association in MapOrIter.

    Unless MapOrIter is an ordered iterator returned by iterator/2, the order of the Fun(Key, Value) calls is not defined.

    The call fails with a {badmap,Map} exception if MapOrIter is not a map or -valid iterator, or with badarg if Fun is not a function of arity 2.

    Examples

    1> Fun = fun(K, V) -> self() ! {K,V} end.
    -2> Map = #{p => 1, q => 2,x => 10, y => 20, z => 30}.
    -3> maps:foreach(Fun, maps:iterator(Map, ordered)).
    +valid iterator, or with badarg if Fun is not a function of arity 2.

    Examples

    1> Fun = fun(K, V) -> self() ! {K,V} end.
    +2> Map = #{p => 1, q => 2,x => 10, y => 20, z => 30}.
    +3> maps:foreach(Fun, maps:iterator(Map, ordered)).
     ok
    -4> [receive X -> X end || _ <- [1,2,3,4,5]].
    -[{p,1},{q,2},{x,10},{y,20},{z,30}]
    +4>
    [receive X -> X end || _ <- [1,2,3,4,5]]. +[{p,1},{q,2},{x,10},{y,20},{z,30}]
    @@ -899,9 +899,9 @@

    Takes a list of keys and a value and builds a map where all keys are -associated with the same value.

    Examples

    1> Keys = ["a", "b", "c"].
    -2> maps:from_keys(Keys, ok).
    -#{"a" => ok,"b" => ok,"c" => ok}
    +associated with the same value.

    Examples

    1> Keys = ["a", "b", "c"].
    +2> maps:from_keys(Keys, ok).
    +#{"a" => ok,"b" => ok,"c" => ok}
    @@ -932,9 +932,9 @@

    Takes a list of key-value tuples and builds a map.

    If the same key appears more than once, the last (rightmost) value is -used, and previous values are ignored.

    Examples

    1> List = [{"a",ignored},{1337,"value two"},{42,value_three},{"a",1}].
    -2> maps:from_list(List).
    -#{42 => value_three,1337 => "value two","a" => 1}
    +used, and previous values are ignored.

    Examples

    1> List = [{"a",ignored},{1337,"value two"},{42,value_three},{"a",1}].
    +2> maps:from_list(List).
    +#{42 => value_three,1337 => "value two","a" => 1}
    @@ -966,8 +966,8 @@

    Returns value Value associated with Key if Map contains Key.

    The call fails with a {badmap,Map} exception if Map is not a map, or with a {badkey,Key} exception if no value is associated with Key.

    Examples

    1> Key = 1337.
    -2> Map = #{42 => value_two,1337 => "value one","a" => 1}.
    -3> maps:get(Key, Map).
    +2> Map = #{42 => value_two,1337 => "value one","a" => 1}.
    +3> maps:get(Key, Map).
     "value one"
    @@ -999,11 +999,11 @@

    Returns the value associated with key Key in Map, or Default if -Key is not present in the map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Examples

    1> Map = #{key1 => val1, key2 => val2}.
    -#{key1 => val1,key2 => val2}
    -2> maps:get(key1, Map, "Default value").
    +Key is not present in the map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Examples

    1> Map = #{key1 => val1, key2 => val2}.
    +#{key1 => val1,key2 => val2}
    +2> maps:get(key1, Map, "Default value").
     val1
    -3> maps:get(key3, Map, "Default value").
    +3> maps:get(key3, Map, "Default value").
     "Default value"
    @@ -1043,13 +1043,13 @@

    Partitions the given List into a map of groups.

    The result is a map where each key is given by KeyFun and each value is a list of elements from the given List for which KeyFun returned the same key.

    The order of elements within each group list is preserved from the original -list.

    Examples

    1> EvenOdd = fun(X) when X rem 2 =:= 0 -> even;
    -                (_) -> odd
    +list.

    Examples

    1> EvenOdd = fun(X) when X rem 2 =:= 0 -> even;
    +                (_) -> odd
                  end.
    -2> maps:groups_from_list(EvenOdd, [1, 2, 3]).
    -#{even => [2], odd => [1, 3]}
    -3> maps:groups_from_list(fun length/1, ["ant", "buffalo", "cat", "dingo"]).
    -#{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}
    +2>
    maps:groups_from_list(EvenOdd, [1, 2, 3]). +#{even => [2], odd => [1, 3]} +3> maps:groups_from_list(fun length/1, ["ant", "buffalo", "cat", "dingo"]). +#{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}
    @@ -1091,15 +1091,15 @@

    Partitions the given List into a map of groups.

    The result is a map where each key is given by KeyFun and each value is a list of elements from the given List, mapped via ValueFun, for which KeyFun returned the same key.

    The order of elements within each group list is preserved from the original -list.

    Examples

    1> EvenOdd = fun(X) -> case X rem 2 of 0 -> even; 1 -> odd end end.
    -2> Square = fun(X) -> X * X end.
    -3> maps:groups_from_list(EvenOdd, Square, [1, 2, 3]).
    -#{even => [4], odd => [1, 9]}
    -4> maps:groups_from_list(
    +list.

    Examples

    1> EvenOdd = fun(X) -> case X rem 2 of 0 -> even; 1 -> odd end end.
    +2> Square = fun(X) -> X * X end.
    +3> maps:groups_from_list(EvenOdd, Square, [1, 2, 3]).
    +#{even => [4], odd => [1, 9]}
    +4> maps:groups_from_list(
         fun length/1,
         fun lists:reverse/1,
    -    ["ant", "buffalo", "cat", "dingo"]).
    -#{3 => ["tna", "tac"],5 => ["ognid"],7 => ["olaffub"]}
    +
    ["ant", "buffalo", "cat", "dingo"]). +#{3 => ["tna", "tac"],5 => ["ognid"],7 => ["olaffub"]}
    @@ -1133,10 +1133,10 @@

    Computes the intersection of maps Map1 and Map2, producing a single map Map3.

    If a key exists in both maps, the value in Map1 is superseded by the value in Map2. Keys existing in only one of the maps are discarded -along with their values.

    The call fails with a {badmap,Map} exception if Map1 or Map2 is not a map.

    Examples

    1> Map1 = #{a => "one", b => "two"}.
    -2> Map2 = #{a => 1, c => 3}.
    -3> maps:intersect(Map1, Map2).
    -#{a => 1}
    +along with their values.

    The call fails with a {badmap,Map} exception if Map1 or Map2 is not a map.

    Examples

    1> Map1 = #{a => "one", b => "two"}.
    +2> Map2 = #{a => 1, c => 3}.
    +3> maps:intersect(Map1, Map2).
    +#{a => 1}
    @@ -1177,10 +1177,10 @@ first parameter, the value from Map1 is the second parameter, and the value from Map2 is the third parameter.

    The call fails with a {badmap,Map} exception if Map1 or Map2 is not a map. The call fails with a badarg exception if Combiner is not a fun that takes -three arguments.

    Examples

    1> Map1 = #{a => "one", b => "two"}.
    -2> Map2 = #{a => 1, c => 3}.
    -3> maps:intersect_with(fun(_Key, Val1, Val2) -> {Val1, Val2} end, Map1, Map2).
    -#{a => {"one",1}}
    +three arguments.

    Examples

    1> Map1 = #{a => "one", b => "two"}.
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/math.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/math.html	2026-08-21 04:00:29.680361530 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/math.html	2026-08-21 04:00:29.680361530 +0000
    @@ -410,7 +410,7 @@
     
           
     
    -

    Returns the arc cosine of X in radians.

    Examples

    1> math:acos(1.0).
    +

    Returns the arc cosine of X in radians.

    Examples

    1> math:acos(1.0).
     0.0
    @@ -439,7 +439,7 @@ -

    Returns the inverse hyperbolic cosine of X.

    Examples

    1> math:acosh(1.0).
    +

    Returns the inverse hyperbolic cosine of X.

    Examples

    1> math:acosh(1.0).
     0.0
    @@ -468,7 +468,7 @@ -

    Returns the arc cosine of X in radians.

    Examples

    1> math:asin(0.0).
    +

    Returns the arc cosine of X in radians.

    Examples

    1> math:asin(0.0).
     0.0
    @@ -497,7 +497,7 @@ -

    Returns the inverse hyperbolic sine of X.

    Examples

    1> math:asinh(0.0).
    +

    Returns the inverse hyperbolic sine of X.

    Examples

    1> math:asinh(0.0).
     0.0
    @@ -527,7 +527,7 @@

    Returns the arc tangent of Y/X in radians, using the signs of both -arguments to determine the quadrant of the return value.

    Examples

    1> math:atan2(0.0, -10.0).
    +arguments to determine the quadrant of the return value.

    Examples

    1> math:atan2(0.0, -10.0).
     3.141592653589793
    @@ -556,7 +556,7 @@ -

    Returns the arc tangent of X in radians.

    Examples

    1> math:atan(0.0).
    +

    Returns the arc tangent of X in radians.

    Examples

    1> math:atan(0.0).
     0.0
    @@ -585,7 +585,7 @@ -

    Returns the inverse hyperbolic tangent of X.

    Examples

    1> math:atanh(0.0).
    +

    Returns the inverse hyperbolic tangent of X.

    Examples

    1> math:atanh(0.0).
     0.0
    @@ -616,11 +616,11 @@ -

    Returns the ceiling of X.

    Examples

    1> math:ceil(7.5).
    +

    Returns the ceiling of X.

    Examples

    1> math:ceil(7.5).
     8.0
    -2> math:ceil(-5.5).
    +2> math:ceil(-5.5).
     -5.0
    -3> math:ceil(1.0).
    +3> math:ceil(1.0).
     1.0
    @@ -649,7 +649,7 @@ -

    Returns the cosine of X in radians.

    Examples

    1> math:cos(0.0)
    +

    Returns the cosine of X in radians.

    Examples

    1> math:cos(0.0)
     1.0
    @@ -678,7 +678,7 @@ -

    Returns the hyperbolic cosine of X.

    Examples

    1> math:cosh(0.0)
    +

    Returns the hyperbolic cosine of X.

    Examples

    1> math:cosh(0.0)
     1.0
    @@ -707,9 +707,9 @@ -

    Returns the error function of X.

    See Error function (Wikipedia).

    Examples

    1> math:erf(0.0).
    +

    Returns the error function of X.

    See Error function (Wikipedia).

    Examples

    1> math:erf(0.0).
     0.0
    -2> math:erf(10.0).
    +2> math:erf(10.0).
     1.0
    @@ -739,7 +739,7 @@

    Returns 1.0 - erf(X), computed using methods -that avoid cancellation for large X.

    Examples

    1> math:erfc(0.0).
    +that avoid cancellation for large X.

    Examples

    1> math:erfc(0.0).
     1.0
    @@ -768,9 +768,9 @@ -

    Returns e raised to the power of X.

    Examples

    1> math:exp(0).
    +

    Returns e raised to the power of X.

    Examples

    1> math:exp(0).
     1.0
    -2> trunc(100 * math:exp(1)).
    +2> trunc(100 * math:exp(1)).
     271
    @@ -801,11 +801,11 @@ -

    Returns the floor of X.

    Examples

    1> math:floor(9.1).
    +

    Returns the floor of X.

    Examples

    1> math:floor(9.1).
     9.0
    -2> math:floor(-1.5).
    +2> math:floor(-1.5).
     -2.0
    -3> math:floor(1.0)
    +3> math:floor(1.0)
     1.0
    @@ -836,7 +836,7 @@ -

    Returns the floating point remainder X divided by Y.

    Examples

    1> math:fmod(10.5, 8.0).
    +

    Returns the floating point remainder X divided by Y.

    Examples

    1> math:fmod(10.5, 8.0).
     2.5
    @@ -867,11 +867,11 @@ -

    Returns logarithm of X to base 2.

    Examples

    1> math:log2(1.0).
    +

    Returns logarithm of X to base 2.

    Examples

    1> math:log2(1.0).
     0.0
    -2> math:log2(2.0).
    +2> math:log2(2.0).
     1.0
    -3> math:log2(64).
    +3> math:log2(64).
     6.0
    @@ -900,11 +900,11 @@ -

    Returns logarithm of X to base 10.

    Examples

    1> math:log10(1.0).
    +

    Returns logarithm of X to base 10.

    Examples

    1> math:log10(1.0).
     0.0
    -2> math:log10(10.0).
    +2> math:log10(10.0).
     1.0
    -3> math:log10(100).
    +3> math:log10(100).
     2.0
    @@ -933,9 +933,9 @@ -

    Returns the natural logarithm of X.

    Examples

    1> math:log(1.0).
    +

    Returns the natural logarithm of X.

    Examples

    1> math:log(1.0).
     0.0
    -2> math:log(2.718281828459045).
    +2> math:log(2.718281828459045).
     1.0
    @@ -964,7 +964,7 @@ /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ms_transform.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2060)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ms_transform.html 2026-08-21 04:00:29.706361699 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ms_transform.html 2026-08-21 04:00:29.706361699 +0000 @@ -113,31 +113,31 @@ table and construct a list of tuples containing relevant parts of the data in these rows. One can use ets:foldl/3 instead, but the ets:select/2 call is far more efficient. Without the translation provided by ms_transform, one must -struggle with writing match specifications terms to accommodate this.

    Consider a simple table of employees:

    -record(emp, {empno,     %Employee number as a string, the key
    +struggle with writing match specifications terms to accommodate this.

    Consider a simple table of employees:

    -record(emp, {empno,     %Employee number as a string, the key
                   surname,   %Surname of the employee
                   givenname, %Given name of employee
                   dept,      %Department, one of {dev,sales,prod,adm}
    -              empyear}). %Year the employee was employed

    We create the table using:

    ets:new(emp_tab, [{keypos,#emp.empno},named_table,ordered_set]).

    We fill the table with randomly chosen data:

    [{emp,"011103","Black","Alfred",sales,2000},
    - {emp,"041231","Doe","John",prod,2001},
    - {emp,"052341","Smith","John",dev,1997},
    - {emp,"076324","Smith","Ella",sales,1995},
    - {emp,"122334","Weston","Anna",prod,2002},
    - {emp,"535216","Chalker","Samuel",adm,1998},
    - {emp,"789789","Harrysson","Joe",adm,1996},
    - {emp,"963721","Scott","Juliana",dev,2003},
    - {emp,"989891","Brown","Gabriel",prod,1999}]

    Assuming that we want the employee numbers of everyone in the sales department, -there are several ways.

    ets:match/2 can be used:

    1> ets:match(emp_tab, {'_', '$1', '_', '_', sales, '_'}).
    -[["011103"],["076324"]]

    ets:match/2 uses a simpler type of match specification, but it is still + empyear}). %Year the employee was employed

    We create the table using:

    ets:new(emp_tab, [{keypos,#emp.empno},named_table,ordered_set]).

    We fill the table with randomly chosen data:

    [{emp,"011103","Black","Alfred",sales,2000},
    + {emp,"041231","Doe","John",prod,2001},
    + {emp,"052341","Smith","John",dev,1997},
    + {emp,"076324","Smith","Ella",sales,1995},
    + {emp,"122334","Weston","Anna",prod,2002},
    + {emp,"535216","Chalker","Samuel",adm,1998},
    + {emp,"789789","Harrysson","Joe",adm,1996},
    + {emp,"963721","Scott","Juliana",dev,2003},
    + {emp,"989891","Brown","Gabriel",prod,1999}]

    Assuming that we want the employee numbers of everyone in the sales department, +there are several ways.

    ets:match/2 can be used:

    1> ets:match(emp_tab, {'_', '$1', '_', '_', sales, '_'}).
    +[["011103"],["076324"]]

    ets:match/2 uses a simpler type of match specification, but it is still unreadable, and one has little control over the returned result. It is always a -list of lists.

    ets:foldl/3 or ets:foldr/3 can be used to avoid the nested lists:

    ets:foldr(fun(#emp{empno = E, dept = sales},Acc) -> [E | Acc];
    -             (_,Acc) -> Acc
    +list of lists.

    ets:foldl/3 or ets:foldr/3 can be used to avoid the nested lists:

    ets:foldr(fun(#emp{empno = E, dept = sales},Acc) -> [E | Acc];
    +             (_,Acc) -> Acc
               end,
    -          [],
    -          emp_tab).

    The result is ["011103","076324"]. The fun is straightforward, so the only + [], + emp_tab).

    The result is ["011103","076324"]. The fun is straightforward, so the only problem is that all the data from the table must be transferred from the table to the calling process for filtering. That is inefficient compared to the ets:match/2 call where the filtering can be done "inside" the emulator and -only the result is transferred to the process.

    Consider a "pure" ets:select/2 call that does what ets:foldr does:

    ets:select(emp_tab, [{#emp{empno = '$1', dept = sales, _='_'},[],['$1']}]).

    Although the record syntax is used, it is still hard to read and even harder to +only the result is transferred to the process.

    Consider a "pure" ets:select/2 call that does what ets:foldr does:

    ets:select(emp_tab, [{#emp{empno = '$1', dept = sales, _='_'},[],['$1']}]).

    Although the record syntax is used, it is still hard to read and even harder to write. The first element of the tuple, #emp{empno = '$1', dept = sales, _='_'}, tells what to match. Elements not matching this are not returned, as in the ets:match/2 example. The second @@ -148,12 +148,12 @@ hence the employee number is returned. The result is ["011103","076324"], as in the ets:foldr/3 example, but the result is retrieved much more efficiently in terms of execution speed and memory consumption.

    Using ets:fun2ms/1, we can combine the ease of use of the ets:foldr/3 and -the efficiency of the pure ets:select/2 example:

    -include_lib("stdlib/include/ms_transform.hrl").
    +the efficiency of the pure ets:select/2 example:

    -include_lib("stdlib/include/ms_transform.hrl").
     
    -ets:select(emp_tab, ets:fun2ms(
    -                      fun(#emp{empno = E, dept = sales}) ->
    +ets:select(emp_tab, ets:fun2ms(
    +                      fun(#emp{empno = E, dept = sales}) ->
                                   E
    -                      end)).

    This example requires no special knowledge of match specifications to + end)).

    This example requires no special knowledge of match specifications to understand. The head of the fun matches what you want to filter out and the body returns what you want returned. As long as the fun can be kept within the limits of the match specifications, there is no need to transfer all table data to the @@ -169,28 +169,28 @@ specifications by hand.

    Example 2

    Assume that we want to get all the employee numbers of employees hired before year 2000. Using ets:match/2 is not an alternative here, as relational operators cannot be expressed there. Once again, ets:foldr/3 can do it -(slowly, but correct):

    ets:foldr(fun(#emp{empno = E, empyear = Y},Acc) when Y < 2000 -> [E | Acc];
    -                  (_,Acc) -> Acc
    +(slowly, but correct):

    ets:foldr(fun(#emp{empno = E, empyear = Y},Acc) when Y < 2000 -> [E | Acc];
    +                  (_,Acc) -> Acc
               end,
    -          [],
    -          emp_tab).

    The result is ["052341","076324","535216","789789","989891"], as expected. The + [], + emp_tab).

    The result is ["052341","076324","535216","789789","989891"], as expected. The equivalent expression using a handwritten match specification would look like -this:

    ets:select(emp_tab, [{#emp{empno = '$1', empyear = '$2', _='_'},
    -                     [{'<', '$2', 2000}],
    -                     ['$1']}]).

    This gives the same result. [{'<', '$2', 2000}] is in the guard part and +this:

    ets:select(emp_tab, [{#emp{empno = '$1', empyear = '$2', _='_'},
    +                     [{'<', '$2', 2000}],
    +                     ['$1']}]).

    This gives the same result. [{'<', '$2', 2000}] is in the guard part and therefore discards anything that does not have an empyear (bound to '$2' in -the head) less than 2000, as the guard in the foldr/3 example.

    We write it using ets:fun2ms/1:

    -include_lib("stdlib/include/ms_transform.hrl").
    +the head) less than 2000, as the guard in the foldr/3 example.

    We write it using ets:fun2ms/1:

    -include_lib("stdlib/include/ms_transform.hrl").
     
    -ets:select(emp_tab, ets:fun2ms(
    -                      fun(#emp{empno = E, empyear = Y}) when Y < 2000 ->
    +ets:select(emp_tab, ets:fun2ms(
    +                      fun(#emp{empno = E, empyear = Y}) when Y < 2000 ->
                                E
    -                      end)).

    Example 3

    Assume that we want the whole object matching instead of only one element. One + end)).

    Example 3

    Assume that we want the whole object matching instead of only one element. One alternative is to assign a variable to every part of the record and build it up -once again in the body of the fun, but the following is easier:

    ets:select(emp_tab, ets:fun2ms(
    -                      fun(Obj = #emp{empno = E, empyear = Y})
    +once again in the body of the fun, but the following is easier:

    ets:select(emp_tab, ets:fun2ms(
    +                      fun(Obj = #emp{empno = E, empyear = Y})
                              when Y < 2000 ->
                                   Obj
    -                      end)).

    As in ordinary Erlang matching, you can bind a variable to the whole matched + end)).

    As in ordinary Erlang matching, you can bind a variable to the whole matched object using a "match inside the match", that is, a =. Unfortunately in funs translated to match specifications, it is allowed only at the "top-level", that is, matching the whole object arriving to be matched into a separate variable. @@ -199,34 +199,34 @@ object/0 also returns the whole matched object, see section Warnings and Restrictions.

    Example 4

    This example concerns the body of the fun. Assume that all employee numbers beginning with zero (0) must be changed to begin with one (1) instead, and -that we want to create the list [{<Old empno>,<New empno>}]:

    ets:select(emp_tab, ets:fun2ms(
    -                      fun(#emp{empno = [$0 | Rest] }) ->
    -                              {[$0|Rest],[$1|Rest]}
    -                      end)).

    This query hits the feature of partially bound keys in table type ordered_set, +that we want to create the list [{<Old empno>,<New empno>}]:

    ets:select(emp_tab, ets:fun2ms(
    +                      fun(#emp{empno = [$0 | Rest] }) ->
    +                              {[$0|Rest],[$1|Rest]}
    +                      end)).

    This query hits the feature of partially bound keys in table type ordered_set, so that not the whole table needs to be searched, only the part containing keys beginning with 0 is looked into.

    Example 5

    The fun can have many clauses. Assume that we want to do the following:

    • If an employee started before 1997, return the tuple {inventory, <employee number>}.
    • If an employee started 1997 or later, but before 2001, return {rookie, <employee number>}.
    • For all other employees, return {newbie, <employee number>}, except for those named Smith as they would be affronted by anything other than the tag guru and that is also what is returned for their numbers: -{guru, <employee number>}.

    This is accomplished as follows:

    ets:select(emp_tab, ets:fun2ms(
    -                      fun(#emp{empno = E, surname = "Smith" }) ->
    -                              {guru,E};
    -                         (#emp{empno = E, empyear = Y}) when Y < 1997  ->
    -                              {inventory, E};
    -                         (#emp{empno = E, empyear = Y}) when Y > 2001  ->
    -                              {newbie, E};
    -                         (#emp{empno = E, empyear = Y}) -> % 1997 -- 2001
    -                              {rookie, E}
    -                      end)).

    The result is as follows:

    [{rookie,"011103"},
    - {rookie,"041231"},
    - {guru,"052341"},
    - {guru,"076324"},
    - {newbie,"122334"},
    - {rookie,"535216"},
    - {inventory,"789789"},
    - {newbie,"963721"},
    - {rookie,"989891"}]

    Useful BIFs

    What more can you do? A simple answer is: see the documentation of +{guru, <employee number>}.

    This is accomplished as follows:

    ets:select(emp_tab, ets:fun2ms(
    +                      fun(#emp{empno = E, surname = "Smith" }) ->
    +                              {guru,E};
    +                         (#emp{empno = E, empyear = Y}) when Y < 1997  ->
    +                              {inventory, E};
    +                         (#emp{empno = E, empyear = Y}) when Y > 2001  ->
    +                              {newbie, E};
    +                         (#emp{empno = E, empyear = Y}) -> % 1997 -- 2001
    +                              {rookie, E}
    +                      end)).

    The result is as follows:

    [{rookie,"011103"},
    + {rookie,"041231"},
    + {guru,"052341"},
    + {guru,"076324"},
    + {newbie,"122334"},
    + {rookie,"535216"},
    + {inventory,"789789"},
    + {newbie,"963721"},
    + {rookie,"989891"}]

    Useful BIFs

    What more can you do? A simple answer is: see the documentation of match specifications in ERTS User's Guide. However, the following is a brief overview of the most useful "built-in functions" that you can use when the fun is to be translated into a match specification by @@ -261,18 +261,18 @@ more, as filtering using Erlang code is not a good idea when tracing (except afterwards, if you trace to file). The concept is similar to that of ets:fun2ms/1 except that you usually use it directly from the shell (which can -also be done with ets:fun2ms/1).

    The following is an example module to trace on:

    -module(toy).
    +also be done with ets:fun2ms/1).

    The following is an example module to trace on:

    -module(toy).
     
    --export([start/1, store/2, retrieve/1]).
    +-export([start/1, store/2, retrieve/1]).
     
    -start(Args) ->
    -    toy_table = ets:new(toy_table, Args).
    +start(Args) ->
    +    toy_table = ets:new(toy_table, Args).
     
    -store(Key, Value) ->
    -    ets:insert(toy_table, {Key,Value}).
    +store(Key, Value) ->
    +    ets:insert(toy_table, {Key,Value}).
     
    -retrieve(Key) ->
    -    [{Key, Value}] = ets:lookup(toy_table, Key),
    +retrieve(Key) ->
    +    [{Key, Value}] = ets:lookup(toy_table, Key),
         Value.

    During model testing, the first test results in {badmatch,16} in {toy,start,1}, why?

    We suspect the ets:new/2 call, as we match hard on the return value, but want only the particular new/2 call with toy_table as first parameter. So we @@ -281,32 +281,32 @@ trace pattern, so there is no need to call trace only a few processes (usually it is not):

    2> dbg:p(all,call).
     {ok,[{matched,nonode@nohost,25}]}

    We specify the filter, we want to view calls that resemble -ets:new(toy_table, <something>):

    3> dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> true end)).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (11968))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/notes.html	2026-08-21 04:00:29.791362252 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/notes.html	2026-08-21 04:00:29.791362252 +0000
    @@ -89,49 +89,49 @@
       
     
     
    -

    This document describes the changes made to the STDLIB application.

    STDLIB 7.3.0.1

    Fixed Bugs and Malfunctions

    • Fixed a bug where zip:unzip/1,2 and zip:extract/1,2 were vulnerable to a relative path traversal attack. A crafted zip archive containing entry names such as ../x/y could have caused files to be written outside the intended extraction directory.

      Thanks to Jonatan Männchen and Zhang Delong for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

      Own Id: OTP-20143 Aux Id: CVE-2026-47078, PR-11386

    STDLIB 7.3

    Fixed Bugs and Malfunctions

    • Fixed functions ets:init_table/2, ets:tab2file/2,3, ets:table/1,2, ets:i/0,1, dets:from_ets/2, and dets:to_ets/2 to resolve named table arguments only once. This will prevent strange effects if the named table is deleted and recreated by a concurrent process.

      Own Id: OTP-19911 Aux Id: PR-10536

    • Corrected the af_zip_generator() type in the parser and syntax_tools.

      Own Id: OTP-19939

    • For a function that started with a bracket-only pattern (such as []), the ?FUNCTION_ARITY macro would evaluate to one less than the actual arity.

      Own Id: OTP-19988 Aux Id: GH-10705, PR-10708

    Improvements and New Features

    • Added support for zstd compression in the file module.

      Own Id: OTP-19860 Aux Id: PR-10385

    • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

      A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

      make release_docs places the documentation in the released code under the doc folder.

      make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

      The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

      Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

      Improves the source Software-Bill-of-Materials

      • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
      • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
      • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

      Own Id: OTP-19886 Aux Id: PR-10434

    • The removal of the slave and slave modules have been postponed to Erlang/OTP 31.

      The partial removal of the archive feature has been postponed to Erlang/OTP 30.

      Own Id: OTP-19989 Aux Id: PR-10714

    STDLIB 7.2.1

    Fixed Bugs and Malfunctions

    • Fixed bug in ets:update_counter/4 and ets:update_element/4 accepting and inserting a default tuple smaller than the keypos of the table. Such a tuple without a key element would make the table internally inconsistent and might lead to bad behavior at table access, like ERTS runtime crash.

      Now a call to ets:update_counter/4 or ets:update_element/4 will fail with badarg if the key does not exist in the table and the default tuple is too small.

      Own Id: OTP-19962 Aux Id: PR-10616

    STDLIB 7.2

    Fixed Bugs and Malfunctions

    • When creating a tar archive using erl_tar, leading slashes would be kept for filenames with up to 100 characters. The slash would be dropped for longer filenames. This has been corrected to always keep the leading slash.

      Own Id: OTP-19066 Aux Id: PR-8309

    • For some function heads or case expressions with a huge number of clauses, the compiler could spend an inordinate amount of time compiling the code.

      Own Id: OTP-19797 Aux Id: PR-10252

    • Passing a type for a fun as a macro argument would result in a "badly formed argument" error message from the compiler. Example:

      -module(test).
      --define(FOO(X), X).
      --type foo() :: ?FOO(fun(() -> ok)).

      Compiling this module would result in the following error message:

      test.erl:3:17: badly formed argument for macro &#href_anchor"w">
      +

      This document describes the changes made to the STDLIB application.

      STDLIB 7.3.0.1

      Fixed Bugs and Malfunctions

      • Fixed a bug where zip:unzip/1,2 and zip:extract/1,2 were vulnerable to a relative path traversal attack. A crafted zip archive containing entry names such as ../x/y could have caused files to be written outside the intended extraction directory.

        Thanks to Jonatan Männchen and Zhang Delong for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

        Own Id: OTP-20143 Aux Id: CVE-2026-47078, PR-11386

      STDLIB 7.3

      Fixed Bugs and Malfunctions

      • Fixed functions ets:init_table/2, ets:tab2file/2,3, ets:table/1,2, ets:i/0,1, dets:from_ets/2, and dets:to_ets/2 to resolve named table arguments only once. This will prevent strange effects if the named table is deleted and recreated by a concurrent process.

        Own Id: OTP-19911 Aux Id: PR-10536

      • Corrected the af_zip_generator() type in the parser and syntax_tools.

        Own Id: OTP-19939

      • For a function that started with a bracket-only pattern (such as []), the ?FUNCTION_ARITY macro would evaluate to one less than the actual arity.

        Own Id: OTP-19988 Aux Id: GH-10705, PR-10708

      Improvements and New Features

      • Added support for zstd compression in the file module.

        Own Id: OTP-19860 Aux Id: PR-10385

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      • The removal of the slave and slave modules have been postponed to Erlang/OTP 31.

        The partial removal of the archive feature has been postponed to Erlang/OTP 30.

        Own Id: OTP-19989 Aux Id: PR-10714

      STDLIB 7.2.1

      Fixed Bugs and Malfunctions

      • Fixed bug in ets:update_counter/4 and ets:update_element/4 accepting and inserting a default tuple smaller than the keypos of the table. Such a tuple without a key element would make the table internally inconsistent and might lead to bad behavior at table access, like ERTS runtime crash.

        Now a call to ets:update_counter/4 or ets:update_element/4 will fail with badarg if the key does not exist in the table and the default tuple is too small.

        Own Id: OTP-19962 Aux Id: PR-10616

      STDLIB 7.2

      Fixed Bugs and Malfunctions

      • When creating a tar archive using erl_tar, leading slashes would be kept for filenames with up to 100 characters. The slash would be dropped for longer filenames. This has been corrected to always keep the leading slash.

        Own Id: OTP-19066 Aux Id: PR-8309

      • For some function heads or case expressions with a huge number of clauses, the compiler could spend an inordinate amount of time compiling the code.

        Own Id: OTP-19797 Aux Id: PR-10252

      • Passing a type for a fun as a macro argument would result in a "badly formed argument" error message from the compiler. Example:

        -module(test).
        +-define(FOO(X), X).
        +-type foo() :: ?FOO(fun(() -> ok)).

        Compiling this module would result in the following error message:

        test.erl:3:17: badly formed argument for macro &#href_anchor"w">
         %    5| -type foo() :: ?FOO(fun(() -> ok)).
        -%

        Own Id: OTP-19821 Aux Id: GH-10280, PR-10309

      • Fixed an issue that prohibited the use of user defined functions within a restricted shell.

        Own Id: OTP-19833 Aux Id: PR-10315

      • The deprecated function crypto:rand_uniform/2 has gotten a new replacement function crypto:strong_rand_range/1. When implementing this the documentation of crypto and rand has been rewritten a bit and improved.

        Own Id: OTP-19841 Aux Id: PR-10344

      • Fixed a bug in the shell where a reference to a locally defined function would cause a crash.

        Own Id: OTP-19850 Aux Id: GH-10294

      Improvements and New Features

      • You are now able to read the reference manual with man.

        Own Id: OTP-19787 Aux Id: PR-10237

      • Improved spec for ets:lookup_element/4.

        Own Id: OTP-19798 Aux Id: PR-10236

      • The mnesia_registry module will be removed in Erlang/OTP 29.

        Own Id: OTP-19808 Aux Id: PR-10275

      STDLIB 7.1

      Fixed Bugs and Malfunctions

      • The save_module/1 command in the shell now saves both the locally defined records and the imported records using the rr/1 command.

        Own Id: OTP-19647 Aux Id: GH-9816, PR-9897

      • It's now possible to write lists:map(fun is_atom/1, []) or lists:map(fun my_func/1, []) in the shell, instead of lists:map(fun erlang:is_atom/1, []) or lists:map(fun shell_default:my_func/1, []).

        Own Id: OTP-19649 Aux Id: GH-9771, PR-9898

      • The shell no longer crashes when requesting to auto-complete map keys containing non-atoms.

        Own Id: OTP-19659 Aux Id: PR-9896

      • A remote shell can now exit by closing the input stream, without terminating the remote node.

        Own Id: OTP-19667 Aux Id: PR-9912

      • Fixed guard check for is_record/2 in the linter.

        Own Id: OTP-19704 Aux Id: GH-10020, PR-10034

      Improvements and New Features

      • Added a flag option shell_hints and function shell:hints/1. You can now disable the warning in the shell when a command is taking longer than 5 seconds.

        Own Id: OTP-19759 Aux Id: PR-10121

      STDLIB 7.0.3

      Fixed Bugs and Malfunctions

      • Update PCRE2 from 10.45 to 10.46. Fixes potential buffer read overflow on regular expressions with (*scs:) and (*ACCEPT) syntax combined.

        Own Id: OTP-19755 Aux Id: CVE-2025-58050

      STDLIB 7.0.2

      Fixed Bugs and Malfunctions

      • A set of small bugs in sort stability for `lists:sort/1` and `lists:keysort/1` has been fixed. The bug happened for only some, seemingly random, element sequences. Most sorts were stable.

        Sort stability for `lists:sort/1` is only possible to observe when sorting lists with floating point and integer numbers of the same value.

        For `lists:keysort/1` the list had to start with two tuples where the keys or the whole tuples compared equal.

        Own Id: OTP-19673 Aux Id: ERIERL-1240

      • Fixed bug in io_lib:bformat/2 which crashed if format string contained unicode characters.

        Own Id: OTP-19680 Aux Id: PR-9952

      STDLIB 7.0.1

      Fixed Bugs and Malfunctions

      • Properly strip the leading / and drive letter from filepaths when zipping and unzipping archives.

        Thanks to Wander Nauta for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

        Own Id: OTP-19653 Aux Id: CVE-2025-4748, PR-9941

      STDLIB 7.0

      Fixed Bugs and Malfunctions

      • Shell help now orders the commands in alphabetical order.

        Own Id: OTP-19161 Aux Id: PR-8573

      • proc_lib:stop/1,3 (and in extension gen_server:stop/3, gen_statem:stop/3 and so on) have been updated to not throw an error if the process to be stopped exits with the same reason as given to proc_lib:stop/3.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19233 Aux Id: PR-8772

      • The size of an atom in the Erlang source code was limited to 255 bytes in previous releases, meaning that an atom containing only emojis could contain only 63 emojis.

        While atoms are still only allowed to contain 255 characters, the number of bytes is no longer limited.

        External tools that parse the AtU8 chunk of a BEAM file directly need to be updated. Tools that use beam_lib:chunks(Beam, [atoms]) to read the atom table will continue to work.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19285 Aux Id: PR-8913

      • argparse:help/1 now accepts unicode:chardata/0.

        Own Id: OTP-19303 Aux Id: PR-8932

      • The literals chunk in BEAM is no longer compressed, resulting in slightly smaller BEAM files when a BEAM file is stripped using beam_lib:strip_files/1.

        This is a potential incompatibility for tools that read and interpret the contents of the literal chunk. One way to update such tools to work with the new format is to retrieve the chunk using beam_lib:chunks(Beam, [literals]).

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19323 Aux Id: GH-8967, PR-8988

      • The previous digraph_utils:preorder/1 and digraph_utils:postorder/1 did not start the traversal from root nodes. This fix makes both traversals only start or restart from a root node in one of the components, or an arbitrary node if no root node can be visited.

        Own Id: OTP-19393 Aux Id: PR-9171

      • Auto-completion in the shell is now significantly faster for function parameters that uses complex custom types.

        Own Id: OTP-19413 Aux Id: PR-9271

      • Stringfying a non-latin1 atom will now produce a readable string instead of encoding each character using \x{...} escape sequences. Example:

        -define(S(T), ??T).
        +%

        Own Id: OTP-19821 Aux Id: GH-10280, PR-10309

      • Fixed an issue that prohibited the use of user defined functions within a restricted shell.

        Own Id: OTP-19833 Aux Id: PR-10315

      • The deprecated function crypto:rand_uniform/2 has gotten a new replacement function crypto:strong_rand_range/1. When implementing this the documentation of crypto and rand has been rewritten a bit and improved.

        Own Id: OTP-19841 Aux Id: PR-10344

      • Fixed a bug in the shell where a reference to a locally defined function would cause a crash.

        Own Id: OTP-19850 Aux Id: GH-10294

      Improvements and New Features

      • You are now able to read the reference manual with man.

        Own Id: OTP-19787 Aux Id: PR-10237

      • Improved spec for ets:lookup_element/4.

        Own Id: OTP-19798 Aux Id: PR-10236

      • The mnesia_registry module will be removed in Erlang/OTP 29.

        Own Id: OTP-19808 Aux Id: PR-10275

      STDLIB 7.1

      Fixed Bugs and Malfunctions

      • The save_module/1 command in the shell now saves both the locally defined records and the imported records using the rr/1 command.

        Own Id: OTP-19647 Aux Id: GH-9816, PR-9897

      • It's now possible to write lists:map(fun is_atom/1, []) or lists:map(fun my_func/1, []) in the shell, instead of lists:map(fun erlang:is_atom/1, []) or lists:map(fun shell_default:my_func/1, []).

        Own Id: OTP-19649 Aux Id: GH-9771, PR-9898

      • The shell no longer crashes when requesting to auto-complete map keys containing non-atoms.

        Own Id: OTP-19659 Aux Id: PR-9896

      • A remote shell can now exit by closing the input stream, without terminating the remote node.

        Own Id: OTP-19667 Aux Id: PR-9912

      • Fixed guard check for is_record/2 in the linter.

        Own Id: OTP-19704 Aux Id: GH-10020, PR-10034

      Improvements and New Features

      • Added a flag option shell_hints and function shell:hints/1. You can now disable the warning in the shell when a command is taking longer than 5 seconds.

        Own Id: OTP-19759 Aux Id: PR-10121

      STDLIB 7.0.3

      Fixed Bugs and Malfunctions

      • Update PCRE2 from 10.45 to 10.46. Fixes potential buffer read overflow on regular expressions with (*scs:) and (*ACCEPT) syntax combined.

        Own Id: OTP-19755 Aux Id: CVE-2025-58050

      STDLIB 7.0.2

      Fixed Bugs and Malfunctions

      • A set of small bugs in sort stability for `lists:sort/1` and `lists:keysort/1` has been fixed. The bug happened for only some, seemingly random, element sequences. Most sorts were stable.

        Sort stability for `lists:sort/1` is only possible to observe when sorting lists with floating point and integer numbers of the same value.

        For `lists:keysort/1` the list had to start with two tuples where the keys or the whole tuples compared equal.

        Own Id: OTP-19673 Aux Id: ERIERL-1240

      • Fixed bug in io_lib:bformat/2 which crashed if format string contained unicode characters.

        Own Id: OTP-19680 Aux Id: PR-9952

      STDLIB 7.0.1

      Fixed Bugs and Malfunctions

      • Properly strip the leading / and drive letter from filepaths when zipping and unzipping archives.

        Thanks to Wander Nauta for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

        Own Id: OTP-19653 Aux Id: CVE-2025-4748, PR-9941

      STDLIB 7.0

      Fixed Bugs and Malfunctions

      • Shell help now orders the commands in alphabetical order.

        Own Id: OTP-19161 Aux Id: PR-8573

      • proc_lib:stop/1,3 (and in extension gen_server:stop/3, gen_statem:stop/3 and so on) have been updated to not throw an error if the process to be stopped exits with the same reason as given to proc_lib:stop/3.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19233 Aux Id: PR-8772

      • The size of an atom in the Erlang source code was limited to 255 bytes in previous releases, meaning that an atom containing only emojis could contain only 63 emojis.

        While atoms are still only allowed to contain 255 characters, the number of bytes is no longer limited.

        External tools that parse the AtU8 chunk of a BEAM file directly need to be updated. Tools that use beam_lib:chunks(Beam, [atoms]) to read the atom table will continue to work.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19285 Aux Id: PR-8913

      • argparse:help/1 now accepts unicode:chardata/0.

        Own Id: OTP-19303 Aux Id: PR-8932

      • The literals chunk in BEAM is no longer compressed, resulting in slightly smaller BEAM files when a BEAM file is stripped using beam_lib:strip_files/1.

        This is a potential incompatibility for tools that read and interpret the contents of the literal chunk. One way to update such tools to work with the new format is to retrieve the chunk using beam_lib:chunks(Beam, [literals]).

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19323 Aux Id: GH-8967, PR-8988

      • The previous digraph_utils:preorder/1 and digraph_utils:postorder/1 did not start the traversal from root nodes. This fix makes both traversals only start or restart from a root node in one of the components, or an arbitrary node if no root node can be visited.

        Own Id: OTP-19393 Aux Id: PR-9171

      • Auto-completion in the shell is now significantly faster for function parameters that uses complex custom types.

        Own Id: OTP-19413 Aux Id: PR-9271

      • Stringfying a non-latin1 atom will now produce a readable string instead of encoding each character using \x{...} escape sequences. Example:

        -define(S(T), ??T).
         
        -atom() ->
        -    ?S(&#href_anchor"p" data-group-id="2850499290-4">).

        The atom/0 function now returns "'атом'" instead of "'\\x{430}\\x{442}\\x{43E}\\x{43C}'".

        Own Id: OTP-19421 Aux Id: GH-9173, PR-9276

      • A few minor issues were corrected in m:syntax_tools, as well in the erl_anno module.

        Own Id: OTP-19422 Aux Id: PR-9253

      • dets could print error messages to standard output when repairing DETS files. This has been changed to send the messages to logger.

        ets:fun2ms would print an error message to standard output as well as returning an error tuple. The printing of the message has been removed.

        Own Id: OTP-19427 Aux Id: PR-9232, PR-9446

      • The functions for converting to and from the RFC1339 date and time format would not properly handle fractional seconds for negative times.

        Own Id: OTP-19441 Aux Id: GH-9279, PR-9280

      • Replaced calls to deprecated crypto:start() with application:start(crypto).

        Own Id: OTP-19485 Aux Id: PR-8592

      • Fixed a bug when calling shell completion on a reserved word followed by a ( would crash the shell.

        Own Id: OTP-19511 Aux Id: GH-9470

      • Corrected the spec of ets:update_element/4.

        Own Id: OTP-19514 Aux Id: PR-9504

      • Corrected the spec for ets:info/1.

        Own Id: OTP-19515 Aux Id: PR-9514

      • Fixed crash when defining records with a string field in the shell

        Own Id: OTP-19533 Aux Id: GH-9557

      • Details in the hibernation implementation and time-out handling has been improved for gen_statem. In particular to avoid selective receive when cancelling a time-out.

        Own Id: OTP-19540 Aux Id: PR-9579

      • Fixed a bug when getting help on a module compiled without debug_info.

        Own Id: OTP-19583 Aux Id: PR-9654

      • Fix zip extraction to wrap invalid DOS timestamps to their correct value instead of returning the actual value. Before this fix the timestamp returned could have a second greater than 59. The bug has been present since Erlang/OTP 27.1.

        Own Id: OTP-19593 Aux Id: PR-9537, GH-9536

      • Enhance specs of timeout for improving documentation and dialyzer analysis.

        Own Id: OTP-19604 Aux Id: PR-9574

      Improvements and New Features

      • Singleton type variables in an union type do not make sense from Dialyzer's point of view. The following example is ill-typed:

        -spec run_test(Opts) -> term()
        -      when Opts :: {join_specs, Bool} | {test, Bool}.

        This used to be reported as a warning. In OTP-28, this is an error

        Own Id: OTP-19125 Aux Id: PR-8556

      • By default, sets created by the sets module will now be represented as maps.

        Own Id: OTP-19127 Aux Id: PR-8429

      • For various error types, the compiler now tries to suggest potential fixes by adding "did you mean ...?" at the end of error messages.

        When a function is used with wrong arity, the compiler will try to suggest a defined function with the same name but a different arity. For example, given the following module:

        -module(typos).
        --export([t/0]).
        -bar(A) -> A.
        -bar(A,A,A) -> A.
        -bar(A,A,A,A) -> A.
        -t() -> bar(0, 0).

        The compiler will emit the following message:

        typo.erl:6:12: function bar/2 undefined, did you mean bar/1,3,4?
        +atom() ->
        +    ?S(&#href_anchor"p" data-group-id="4912138320-4">).

        The atom/0 function now returns "'атом'" instead of "'\\x{430}\\x{442}\\x{43E}\\x{43C}'".

        Own Id: OTP-19421 Aux Id: GH-9173, PR-9276

      • A few minor issues were corrected in m:syntax_tools, as well in the erl_anno module.

        Own Id: OTP-19422 Aux Id: PR-9253

      • dets could print error messages to standard output when repairing DETS files. This has been changed to send the messages to logger.

        ets:fun2ms would print an error message to standard output as well as returning an error tuple. The printing of the message has been removed.

        Own Id: OTP-19427 Aux Id: PR-9232, PR-9446

      • The functions for converting to and from the RFC1339 date and time format would not properly handle fractional seconds for negative times.

        Own Id: OTP-19441 Aux Id: GH-9279, PR-9280

      • Replaced calls to deprecated crypto:start() with application:start(crypto).

        Own Id: OTP-19485 Aux Id: PR-8592

      • Fixed a bug when calling shell completion on a reserved word followed by a ( would crash the shell.

        Own Id: OTP-19511 Aux Id: GH-9470

      • Corrected the spec of ets:update_element/4.

        Own Id: OTP-19514 Aux Id: PR-9504

      • Corrected the spec for ets:info/1.

        Own Id: OTP-19515 Aux Id: PR-9514

      • Fixed crash when defining records with a string field in the shell

        Own Id: OTP-19533 Aux Id: GH-9557

      • Details in the hibernation implementation and time-out handling has been improved for gen_statem. In particular to avoid selective receive when cancelling a time-out.

        Own Id: OTP-19540 Aux Id: PR-9579

      • Fixed a bug when getting help on a module compiled without debug_info.

        Own Id: OTP-19583 Aux Id: PR-9654

      • Fix zip extraction to wrap invalid DOS timestamps to their correct value instead of returning the actual value. Before this fix the timestamp returned could have a second greater than 59. The bug has been present since Erlang/OTP 27.1.

        Own Id: OTP-19593 Aux Id: PR-9537, GH-9536

      • Enhance specs of timeout for improving documentation and dialyzer analysis.

        Own Id: OTP-19604 Aux Id: PR-9574

      Improvements and New Features

      • Singleton type variables in an union type do not make sense from Dialyzer's point of view. The following example is ill-typed:

        -spec run_test(Opts) -> term()
        +      when Opts :: {join_specs, Bool} | {test, Bool}.

        This used to be reported as a warning. In OTP-28, this is an error

        Own Id: OTP-19125 Aux Id: PR-8556

      • By default, sets created by the sets module will now be represented as maps.

        Own Id: OTP-19127 Aux Id: PR-8429

      • For various error types, the compiler now tries to suggest potential fixes by adding "did you mean ...?" at the end of error messages.

        When a function is used with wrong arity, the compiler will try to suggest a defined function with the same name but a different arity. For example, given the following module:

        -module(typos).
        +-export([t/0]).
        +bar(A) -> A.
        +bar(A,A,A) -> A.
        +bar(A,A,A,A) -> A.
        +t() -> bar(0, 0).

        The compiler will emit the following message:

        typo.erl:6:12: function bar/2 undefined, did you mean bar/1,3,4?
         %   6|     t() -> bar(0, 0).
        -%    |            ^

        For compiler errors that can easily be caused by typos, the compiler will try to suggest what the correct variable or function name, could be. For example, given the following module:

        -module(typos).
        --export([bar/2]).
        +%    |            ^

        For compiler errors that can easily be caused by typos, the compiler will try to suggest what the correct variable or function name, could be. For example, given the following module:

        -module(typos).
        +-export([bar/2]).
         
        -bar(A0, B0) ->
        +bar(A0, B0) ->
             A + B.

        the compiler will emit the following error messages:

        typos.erl:5:5: variable &#href_anchor"w"> is unbound, did you mean 'A0'?
         %    5|     A + B.
         %     |     ^
         
         typos.erl:5:9: variable 'B' is unbound, did you mean 'B0'?
         %    5|     A + B.
        -%     |         ^

        Error types that now suggest correct arities: bad_inline, undefined_nif, bad_nowarn_unused_function, bad_nowarn_bif_clash, undefined_function.

        Error types that now suggest correct names: bad_inline, undefined_nif, bad_nowarn_unused_function, undefined_on_load, undefined_function, undefined_record, undefined_field, unbound_var.

        Using a function with wrong arity has higher precedence than having a typo in the function name. If the compiler can find a defined function with the same name but a different arity, it will not suggest a defined function with a close-enough name, regardless of arity.

        Own Id: OTP-19180 Aux Id: PR-8699, PR-9094

      • Comprehensions have been extended with zip generators according to EEP 73.

        Example:

        1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
        -[5,7,9]

        Own Id: OTP-19184 Aux Id: PR-8926

      • Before restarting a child, a supervisor must check if the restart limit is reached. This adds a penalty to the overall restart time, which should be kept low. The algorithm +% | ^

      Error types that now suggest correct arities: bad_inline, undefined_nif, bad_nowarn_unused_function, bad_nowarn_bif_clash, undefined_function.

      Error types that now suggest correct names: bad_inline, undefined_nif, bad_nowarn_unused_function, undefined_on_load, undefined_function, undefined_record, undefined_field, unbound_var.

      Using a function with wrong arity has higher precedence than having a typo in the function name. If the compiler can find a defined function with the same name but a different arity, it will not suggest a defined function with a close-enough name, regardless of arity.

      Own Id: OTP-19180 Aux Id: PR-8699, PR-9094

    • Comprehensions have been extended with zip generators according to EEP 73.

      Example:

      1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
      +[5,7,9]

      Own Id: OTP-19184 Aux Id: PR-8926

    • Before restarting a child, a supervisor must check if the restart limit is reached. This adds a penalty to the overall restart time, which should be kept low. The algorithm has been optimized from 2*O(n) to O(n) behavior.

      Own Id: OTP-19204 Aux Id: PR-8261

    • Added the possibility to configure shell docs column width through the stdlib parameter shell_docs_columns.

      Own Id: OTP-19224 Aux Id: PR-8651

    • The io:setopts/2 function now accepts the line_history option for more explicit handling of when to save shell history.

      Own Id: OTP-19230 Aux Id: PR-8792

    • The shell now prints a help message explaining how to interrupt a running command when stuck executing a command for longer than 5 seconds.

      Own Id: OTP-19231 Aux Id: PR-8793

    • Binaries can now be used as input to calendar:rfc3339_to_system_time/2, and produced as output of calendar:system_time_to_rfc3339/2.

      Own Id: OTP-19250 Aux Id: PR-8812

    • The erl -noshell mode has been updated to have two sub modes called raw and cooked, where cooked is the old default behaviour and raw can be used to bypass the line-editing support of the native terminal. Using raw mode it is possible to read keystrokes as they happen without the user having to press Enter. Also, the raw mode does not echo the typed characters to stdout. An example of how to create a tic-tac-toe game using this mechanism is included in the documentation.

      Own Id: OTP-19314 Aux Id: PR-8962, GH-8037

    • Added io:get_password/0 that can read passwords from stdin when in "raw" -noshell mode.

      Own Id: OTP-19315 Aux Id: PR-8962, PR-9006

    • New strict generators have been added for comprehensions.

      The currently existing generators are "relaxed": they ignore terms in the right-hand side expression that do not match the left-hand side pattern.

      The new strict generators fail with exception badmatch if a pattern doesn't match.

      Examples:

      Using the current relaxed generator operator <-, any element not matching -the pattern {_,_} will be silently discarded:

      1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
      -[{ok,1},{error,2}]

      If the intention is that all lists processed by a list comprehension must only +the pattern {_,_} will be silently discarded:

      1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
      +[{ok,1},{error,2}]

      If the intention is that all lists processed by a list comprehension must only contain tuples of size two, using the new strict version of the operator ensures -that term not matching will cause a crash:

      2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
      +that term not matching will cause a crash:

      2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
       ** exception error: no match of right hand side value ok

      Using the strict generator operator to mark the intention that all list elements must match the pattern could help finding mistakes quicker if something unpexected is added to the list processed by the generator.

      The strict version for bitstring generators is <:=.

      Own Id: OTP-19317 Aux Id: PR-8625

    • New options for suppressing behaviour warnings have been added:

      • nowarn_conflicting_behaviours
      • nowarn_undefined_behaviour_func
      • nowarn_undefined_behaviour
      • nowarn_undefined_behaviour_callbacks
      • nowarn_ill_defined_behaviour_callbacks
      • nowarn_ill_defined_optional_callbacks

      Own Id: OTP-19334 Aux Id: GH-8985, PR-9020

    • The join(Binaries, Separator) function that joins a list of binaries has been added to the binary module.

      Own Id: OTP-19337 Aux Id: GH-8099, PR-8100

    • The supervisor:which_child/2 function has been added to facilitate getting the pid of a sibling process; that is a process under same supervisor as the process that calls to call the new function.

      Own Id: OTP-19345 Aux Id: PR-8976

    • The function erl_anno:set_end_location/2 for setting the end location of a token has been added.

      Own Id: OTP-19354 Aux Id: PR-8966

    • Added a warning for calling non-exported functions with the remote function call syntax from the same module, and likewise for the remote fun syntax.

      Own Id: OTP-19371 Aux Id: GH-9092, PR-9095

    • The warn_deprecated_catch option enables warnings for use of old-style catch expressions on the form catch Expr instead of the modern try ... catch ... end. To prevent new uses of uses of old catches to be added, this compiler option can be enabled on the project level and -compile(nowarn_deprecated_catch). added to individual files that still contain old catches.

      Own Id: OTP-19425 Aux Id: PR-9154

    • Module re has been updated to use PCRE2, which is mostly backward compatible with PCRE.

      The most noticeable incompatibilities are

      • The default character encoding is pure ASCII and not Latin1. Unicode support is still available with options unicode and ucp.
      • Options bsr_anycrlf, bsr_unicode and {newline,_} are only set when a -regex is compiled and cannot be changed at matching for precompiled regex.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19431 Aux Id: PR-9299, PR-9610

    • Defining a fun in terms of an imported function is not allowed. Before this release, the compiler would not catch this kind of error if the name of the imported function happened to be a BIF. Consider this example:

      -module(fun_example).
      --export([foo/0, bar/0]).
      --import(m, [max/2, not_a_bif/0]).
      +regex is compiled and cannot be changed at matching for precompiled regex.

    POTENTIAL INCOMPATIBILITY

    Own Id: OTP-19431 Aux Id: PR-9299, PR-9610

  • Defining a fun in terms of an imported function is not allowed. Before this release, the compiler would not catch this kind of error if the name of the imported function happened to be a BIF. Consider this example:

    -module(fun_example).
    +-export([foo/0, bar/0]).
    +-import(m, [max/2, not_a_bif/0]).
     
    -foo() ->
    +foo() ->
         fun max/2.
     
    -bar() ->
    +bar() ->
         fun not_a_bif/0.

    The compiler in Erlang/OTP 27 would generate the following messages:

    fun_example.erl:9:5: function not_a_bif/0 undefined
     %    9|     fun not_a_bif/0.
     %     |     ^
    @@ -150,37 +150,37 @@
     fun_example.erl:3:2: Warning: import directive overrides auto-imported BIF max/2 --
     use "-compile({no_auto_import,[max/2]})." to resolve name clash
     %    3| -import(m, [max/2, not_a_bif/0]).
    -%     |  ^

    Also, attempting to call a local function having the same name as auto-imported BIF would result in an error if the BIF was added to Erlang/OTP before R14, and a warning for newer BIFs. This has been changed to always emit a warning. For example:

    -module(bif_example).
    --export([bar/1]).
    +%     |  ^

    Also, attempting to call a local function having the same name as auto-imported BIF would result in an error if the BIF was added to Erlang/OTP before R14, and a warning for newer BIFs. This has been changed to always emit a warning. For example:

    -module(bif_example).
    +-export([bar/1]).
     
    -bar(B) ->
    -    is_boolean(B).
    +bar(B) ->
    +    is_boolean(B).
     
    -is_boolean(B) ->
    +is_boolean(B) ->
             B =:= true orelse B =:= false.

    will now result in the following warning instead of an error:

    if_example.erl:5:5: Warning: ambiguous call of overridden auto-imported BIF is_boolean/1 --
     use erlang:is_boolean/1 or "-compile({no_auto_import,[is_boolean/1]})." to resolve name clash
     %    5|     is_boolean(B).
     %     |     ^

    Own Id: OTP-19432 Aux Id: PR-9246

  • It is now possible to use any base for floating point numbers as described in EEP 75: Based Floating Point Literals.

    Computers represent floating point numbers in binary, but such numbers are typically printed using base ten, for example 0.314159265e1. To maintain exact bit-level precision when converting numbers to and from text, it is better to use a base that matches the internally used base, such as 16 for a compact but still exact representation, or 2 for visualizing or writing down the exact internal format. One particular case where such exact representations are useful is in code generating tools.

    Examples:

    > 2#href_anchor"p">.111.
     0.875
     > 16#fefe.fefe#e16.
    -1.2041849337671418e24

    Own Id: OTP-19452 Aux Id: PR-9106

  • The callback function handle_continue/2 in gen_server callback modules is now cached like the others, thanks to code cleanup and optimization of the internal behaviour loop.

    This should only improve performance, not affect functionality.

    Own Id: OTP-19474 Aux Id: PR-9333

  • Encoding done by the json module has been optimized.

    Own Id: OTP-19476 Aux Id: PR-9251

  • There is a new zstd module that does Zstandard compression.

    Own Id: OTP-19477 Aux Id: PR-9316

  • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

    Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

  • Functions of a module can now be grouped in the shell code completion by using the group key in the -doc attribute e.g. -doc(#href_anchor"https://github.com/erlang/otp/pull/9408" title="">PR-9408

  • Added calendar:universal_time_to_system_time/1,2 and calendar:local_time_to_system_time/1,2

    Own Id: OTP-19505 Aux Id: PR-9445

  • Improve error messages for json:decode/1.

    Own Id: OTP-19508 Aux Id: PR-9484

  • ETS heir can be set without getting an ETS-TRANSFER message. Useful when the heir is a supervisor process that cannot handle custom messages.

    Own Id: OTP-19512 Aux Id: PR-7970

  • Added support for the Unicode 16 standard.

    Own Id: OTP-19516 Aux Id: PR-9518, PR-9141

  • When documenting a function or type that needs to deal with durations, usually we can document it as "time in milliseconds". Since the timer family of functions (hms, hours, seconds, ...) all return time in milliseconds, it is useful to be able to use this type in type specifications.

    Own Id: OTP-19526 Aux Id: PR-9515

  • A new event time-out has been implemented in gen_server, that behaves more like the one in gen_statem.

    See the type gen_server:action/0 for {timeout|hibernate,...}, and also related functions.

    Own Id: OTP-19537 Aux Id: PR-9287, PR-9615, PR-9621

  • Line numbers used to be reported in the following way:

    1> lists:last([]).
    -** exception error: no function clause matching lists:last([]) (lists.erl, line 389)

    Starting from Erlang/OTP 28, line numbers are now reported in the following way:

    1> lists:last([]).
    +1.2041849337671418e24

    Own Id: OTP-19452 Aux Id: PR-9106

  • The callback function handle_continue/2 in gen_server callback modules is now cached like the others, thanks to code cleanup and optimization of the internal behaviour loop.

    This should only improve performance, not affect functionality.

    Own Id: OTP-19474 Aux Id: PR-9333

  • Encoding done by the json module has been optimized.

    Own Id: OTP-19476 Aux Id: PR-9251

  • There is a new zstd module that does Zstandard compression.

    Own Id: OTP-19477 Aux Id: PR-9316

  • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

    Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

  • Functions of a module can now be grouped in the shell code completion by using the group key in the -doc attribute e.g. -doc(#href_anchor"https://github.com/erlang/otp/pull/9408" title="">PR-9408

  • Added calendar:universal_time_to_system_time/1,2 and calendar:local_time_to_system_time/1,2

    Own Id: OTP-19505 Aux Id: PR-9445

  • Improve error messages for json:decode/1.

    Own Id: OTP-19508 Aux Id: PR-9484

  • ETS heir can be set without getting an ETS-TRANSFER message. Useful when the heir is a supervisor process that cannot handle custom messages.

    Own Id: OTP-19512 Aux Id: PR-7970

  • Added support for the Unicode 16 standard.

    Own Id: OTP-19516 Aux Id: PR-9518, PR-9141

  • When documenting a function or type that needs to deal with durations, usually we can document it as "time in milliseconds". Since the timer family of functions (hms, hours, seconds, ...) all return time in milliseconds, it is useful to be able to use this type in type specifications.

    Own Id: OTP-19526 Aux Id: PR-9515

  • A new event time-out has been implemented in gen_server, that behaves more like the one in gen_statem.

    See the type gen_server:action/0 for {timeout|hibernate,...}, and also related functions.

    Own Id: OTP-19537 Aux Id: PR-9287, PR-9615, PR-9621

  • Line numbers used to be reported in the following way:

    1> lists:last([]).
    +** exception error: no function clause matching lists:last([]) (lists.erl, line 389)

    Starting from Erlang/OTP 28, line numbers are now reported in the following way:

    1> lists:last([]).
     ** exception error: no function clause matching lists:last([]) (lists.erl:389)

    Own Id: OTP-19538 Aux Id: PR-9468

  • Upgrade pcre2 to 10.45

    Own Id: OTP-19541 Aux Id: PR-9582

  • Added functions that produce utf-8 binaries instead of iolists. New functions are: io_lib:bformat/2, io_lib:bformat/3, io_lib:bfwrite/2, io_lib:bfwrite/3, io_lib:bwrite/2 and io_lib:bwrite_string/3.

    Own Id: OTP-19556 Aux Id: PR-9772

  • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

    Own Id: OTP-19575 Aux Id: PR-9670

  • A list of PCRE2 incompatibilities is documented in a user's guide for stdlib.

    Own Id: OTP-19578 Aux Id: PR-9705

  • Change automatic hibernation of static supervisors so that they will hibernate after being idle for 1 second instead of only after starting, dynamic supervisors (simple_one_for_one) will not be hibernated at all. An option to the supervisor is added to make it configurable for the application. This option defaults to 1 second for static supervisors and to infinity for the simple_one_for_one supervisors.

    POTENTIAL INCOMPATIBILITY

    Own Id: OTP-19597 Aux Id: PR-9680

  • STDLIB 6.2.2.3

    Fixed Bugs and Malfunctions

    • Fixed bug in ets:update_counter/4 and ets:update_element/4 accepting and inserting a default tuple smaller than the keypos of the table. Such a tuple without a key element would make the table internally inconsistent and might lead to bad behavior at table access, like ERTS runtime crash.

      Now a call to ets:update_counter/4 or ets:update_element/4 will fail with badarg if the key does not exist in the table and the default tuple is too small.

      Own Id: OTP-19962 Aux Id: PR-10616

    • For a function that started with a bracket-only pattern (such as []), the ?FUNCTION_ARITY macro would evaluate to one less than the actual arity.

      Own Id: OTP-19988 Aux Id: GH-10705, PR-10708

    STDLIB 6.2.2.2

    Fixed Bugs and Malfunctions

    • A set of small bugs in sort stability for `lists:sort/1` and `lists:keysort/1` has been fixed. The bug happened for only some, seemingly random, element sequences. Most sorts were stable.

      Sort stability for `lists:sort/1` is only possible to observe when sorting lists with floating point and integer numbers of the same value.

      For `lists:keysort/1` the list had to start with two tuples where the keys or the whole tuples compared equal.

      Own Id: OTP-19673 Aux Id: ERIERL-1240

    STDLIB 6.2.2.1

    Fixed Bugs and Malfunctions

    • The save_module/1 command in the shell now saves both the locally defined records and the imported records using the rr/1 command.

      Own Id: OTP-19647 Aux Id: GH-9816, PR-9897

    • It's now possible to write lists:map(fun is_atom/1, []) or lists:map(fun my_func/1, []), in the shell, instead of lists:map(fun erlang:is_atom/1, []) or lists:map(fun shell_default:my_func/1, []).

      Own Id: OTP-19649 Aux Id: GH-9771, PR-9898

    • Properly strip the leading / and drive letter from filepaths when zipping and unzipping archives.

      Thanks to Wander Nauta for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

      Own Id: OTP-19653 Aux Id: CVE-2025-4748, PR-9941

    • Shell no longer crashes when requesting to autocomplete map keys containing non-atoms.

      Own Id: OTP-19659 Aux Id: PR-9896

    • A remote shell can now exit by closing the input stream, without terminating the remote node.

      Own Id: OTP-19667 Aux Id: PR-9912

    STDLIB 6.2.2

    Fixed Bugs and Malfunctions

    • Fixed crash when fetching initial_call when user code have modified the process_dictionary.

      Own Id: OTP-19546 Aux Id: ERIERL-1205, PR-9596

    STDLIB 6.2.1

    Fixed Bugs and Malfunctions

    • Fixed argparse:help/2 to accept the program name as part of the command path.

      Own Id: OTP-19397 Aux Id: PR-9160

    • Fixed argparse:format_help/2 crash on 'hidden' command.

      Own Id: OTP-19400 Aux Id: PR-9151, GH-9150

    • Fixed the type specification for timer:sleep/1 by adding the value infinity to its input type.

      Own Id: OTP-19442 Aux Id: PR-9303

    • Eliminated a crash in zip:unzip/1 while unzipping an archive where a directory within was read-only. This bug was introduced in Erlang/OTP 27.1.

      Own Id: OTP-19447 Aux Id: GH-9332, PR-9335

    • Fixed map comprehension result when a key value is replaced.

      Own Id: OTP-19459 Aux Id: GH-9348, PR-9358

    • Fixed string:jaro_similarity/1 for matching strings of length 1.

      Own Id: OTP-19468 Aux Id: PR-9371

    STDLIB 6.2

    Fixed Bugs and Malfunctions

    • Made it possible to expand help text displayed by pressing ^[h by pressing ^[h again.

      Own Id: OTP-19260 Aux Id: PR-8884

    • Defining a fun in the shell using the syntax fun Name/Arity would fail. This has been corrected so that the following now works:

      1> F = fun is_atom/1.
       #href_anchor"n">Fun.erl.42.18682967>
      -> F(a).
      +> F(a).
       true
       3> Id = fun id/1.
       #Fun.erl.42.18682967>
      -4> Id(42).
      +4> Id(42).
       ** exception error: undefined shell command id/1
      -5> id(I) -> I.
      +5> id(I) -> I.
       ok
      -6> Id(42).
      -42

      The Debugger has also been corrected to correctly handle this syntax for a BIF.

      Own Id: OTP-19322 Aux Id: GH-8963, PR-8987

    • Fixed a bug where completion of 'fun(' would cause the shell to crash.

      Own Id: OTP-19351 Aux Id: PR-9043

    • Fixed a bug causing the shell to crash while trying to complete an expression starting with a '/' or a variable followed by '(' or '/'. E.g. Foo/ and Foo(.

      Own Id: OTP-19361 Aux Id: PR-9078

    • zip:extract/2 with keep_old_files now respects the cwd option.

      Own Id: OTP-19370 Aux Id: PR-9097, GH-9087

    • Fixed an error in uri_string:percent_decode spec

      Own Id: OTP-19380 Aux Id: GH-8755

    Improvements and New Features

    • Updated shell docs to display the type spec, that is, h(erlang, min, 2)) now prints the type spec and documentation in the shell.

      > h(erlang,min,2).
      +6> Id(42).
      +42

      The Debugger has also been corrected to correctly handle this syntax for a BIF.

      Own Id: OTP-19322 Aux Id: GH-8963, PR-8987

    • Fixed a bug where completion of 'fun(' would cause the shell to crash.

      Own Id: OTP-19351 Aux Id: PR-9043

    • Fixed a bug causing the shell to crash while trying to complete an expression starting with a '/' or a variable followed by '(' or '/'. E.g. Foo/ and Foo(.

      Own Id: OTP-19361 Aux Id: PR-9078

    • zip:extract/2 with keep_old_files now respects the cwd option.

      Own Id: OTP-19370 Aux Id: PR-9097, GH-9087

    • Fixed an error in uri_string:percent_decode spec

      Own Id: OTP-19380 Aux Id: GH-8755

    Improvements and New Features

    • Updated shell docs to display the type spec, that is, h(erlang, min, 2)) now prints the type spec and documentation in the shell.

      > h(erlang,min,2).
       
      -  -spec min(Term1, Term2) -> Minimum
      -               when Term1 :: term(), Term2 :: term(), Minimum :: term().
      +  -spec min(Term1, Term2) -> Minimum
      +               when Term1 :: term(), Term2 :: term(), Minimum :: term().
       
         Returns the smallest of Term1 and Term2. If the terms compare equal with the == operator, Term1 is returned.

      Own Id: OTP-19234 Aux Id: GH-8544, PR-8833

    • The file:io_device/0 type has been updated to clearly show the difference between a raw and cooked IoDevice.

      Own Id: OTP-19301 Aux Id: PR-8956

    • Added json:format_key_value_list/3 and json:format_key_value_list_checked/3.

      Own Id: OTP-19320 Aux Id: PR-8889

    • Improved documentation of timers.

      Own Id: OTP-19360 Aux Id: ERIERL-1149, PR-9062

    • Added logging support to io:user/0, io:standard_io/0 and io:standard_error/0. See io:setopts/2 for more details.

      Own Id: OTP-19372 Aux Id: PR-8947

    STDLIB 6.1.2

    Fixed Bugs and Malfunctions

    • With this change, uri_string:normalize assumes empty path (do not crash) when no path is provided in the URI map.

      Own Id: OTP-19266 Aux Id: ERIERL-1127, PR-8890

    • Fixed spec for json:format/3.

      Own Id: OTP-19286 Aux Id: GH-8880, PR-8914

    STDLIB 6.1.1

    Fixed Bugs and Malfunctions

    • Remove whitespace stripping of returned binaries in json:decode/3.

      Own Id: OTP-19227 Aux Id: ERIERL-1130, PR-8809

    • Fix zip:unzip/2 to not crash when extracting zip files with garbage in the Zip64 extra header. This bug was introduced in Erlang 27.1 and has so far only been seen on some archives creates by MS Excel.

      Own Id: OTP-19241 Aux Id: PR-8836

    • With this change, shutdown procedure handles a race condition between supervisor executing a shutdown and child process termination from other reason.

      Own Id: OTP-19256 Aux Id: PR-8780

    STDLIB 6.1

    Fixed Bugs and Malfunctions

    • The help printout for incorrect io:format/0 strings now handles the k modifier correctly.

      Own Id: OTP-19146 Aux Id: PR-8611, GH-8568

    • Fixed a bug that caused the shell completion to crash when keyword and tuple appeared on the same line.

      Own Id: OTP-19157 Aux Id: PR-8638

    • Due to PR-7419/OTP-18671, the cached internal value of the callback_mode started leaking out to logger reports, which could cause logger handlers to crash. This has now been fixed to show the value that was set, as before caching.

      Own Id: OTP-19164 Aux Id: GH-8605, PR-7419, OTP-18671

    • Fixed an emulator crash relating to compressed ETS tables.

      Own Id: OTP-19176 Aux Id: PR-8683

    • The error description for maps:update/3 will no longer insist that the third argument is not a map when a key could not be found

      Own Id: OTP-19189

    • Multiple issues have been corrected in the markdown parser that creates documentation for the shell.

      The parser was incorrectly parsing formatted markdown (either bold or italics) within parenthesis. This used to not be shown correctly in the shell documentation (_Option._), which was displayed verbatim. This fix makes Option. to appear in italics.

      The markdown parser is also used in the creation of other documentation formats, so this was a bug that affected other generated documentation formats.

      Own Id: OTP-19200 Aux Id: GH-8738, PR-8739

    • Fixed category for some codepoint ranges in unicode_util.

      Own Id: OTP-19210 Aux Id: GH-8748

    • Fixed argparse to print sub-commands help when available.

      Own Id: OTP-19222 Aux Id: PR-8777

    Improvements and New Features

    • Class annotation to HTML from fenced blocks have been added.

      Own Id: OTP-19105 Aux Id: PR-8499

    • Added JSON formatting functions for indented output.

      Own Id: OTP-19112

    • Improved illegal pattern error for accidental map associations.

      Own Id: OTP-19128 Aux Id: PR-8555

    • Progress reports for a dynamically started supervisor will now be logged at debug level.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19202 Aux Id: PR-8261, GH-8715, PR-8741

    • The zip module has been updated with support for:

      • zip64 archives - Archives larger than 4GB or with more than 2^32 entries.
      • extended timestamps - Higher resolution and in UTC.
      • UID/GID - Save and extract the original UID/GID.
      • Fixes so that permission mode attributes are correctly read and set for files in archives.
      • zip:list_dir/2 now also returns directories, not only files. (You can disable this behaviour by using the option skip_directories).

      Various bugs in the original implementation have also been fixed, such as:

      • Correctly encode and decode the DOS timestamps for entries within an archive (that is the non-extended timestamp).
      • Fix DOS timestamps to be set to localtime instead of UTC (use extended timestamps for UTC timestamps).
      • Use the unix file attributes read from disk when creating archives instead of setting everything to 644.

      Own Id: OTP-19214 Aux Id: PR-8765

    STDLIB 6.0.1

    Fixed Bugs and Malfunctions

    STDLIB 6.0

    Fixed Bugs and Malfunctions

    • The specs in module binary has been updated to reflect what is allowed by the documentation.

      Own Id: OTP-18684 Aux Id: PR-7481

    • Several functions in the binary module would accept arguments of the wrong type under certain circumstances. In this release, they now raise an exception when incorrect types are given.

      The following functions would accept an invalid pattern if the subject binary was empty or if the {scope,{0,0}} option was given: @@ -188,8 +188,8 @@ binary:matches/2,3, binary:replace/3,4, and binary:split/2,3

      The call binary:copy(<<1:1>>, 0) would return an empty binary instead of raising an exception. Similarly, calls to binary:part/2,3 attempting to extract 0 bytes at position 0 of a bitstring would return an empty binary instead of raising an exception.

      Own Id: OTP-18743 Aux Id: PR-7607, PR-7628

    • The documentation for the preprocessor now mentions that defined(Name) can be called in the condition for an -if or -elif directive to test whether Name is the name of a defined macro. (This feature was implemented in OTP 21.)

      If a function call in an -if or -elif with a name that is not the name of a guard BIF, there would not be a compilation error, but would instead cause the lines following the directive to be skipped. This has now been changed to be a compilation error.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-18784 Aux Id: GH-7706, PR-7726

    • get_until requests using the I/O protocol now correctly return a binary or list when eof is the last item returned by the callback.

      Own Id: OTP-18930 Aux Id: PR-7993, GH-4992

    • The error handling the simple_one_for_one supervisor has been enhanced. A transient child returning ignore will no longer cause a crash.

      Also, automatic shutdown has been disabled because it does not make sense for this supervisor type. That is was allowed is considered a bug. Therefore, we don't consider this an incompatible change.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19029 Aux Id: PR-8230

    • Fix shell expansion to not crash when expanding a map with non-atom keys and to not list zero arity functions when an argument has been given.

      Own Id: OTP-19073 Aux Id: PR-8375, GH-8366, GH-8365, GH-8364

    Improvements and New Features

    • The functions is_equal/2, map/2, and filtermap/2 have been added to the modules sets, ordsets, and gb_sets.

      Own Id: OTP-18622 Aux Id: PR-7183, PR-7232

    • The compiler now emits nicer error message for function head mismatches. -For example, given:

      a() -> ok;
      -a(_) -> error.

      Erlang/OTP 26 and earlier would emit a diagnostic similar to:

      t.erl:6:1: head mismatch
      +For example, given:

      a() -> ok;
      +a(_) -> error.

      Erlang/OTP 26 and earlier would emit a diagnostic similar to:

      t.erl:6:1: head mismatch
       %    6| a(_) -> error.
       %     | ^

      while in Erlang/OTP 27 the diagnostic is similar to:

      t.erl:6:1: head mismatch: function a with arities 0 and 1 is regarded as two distinct functions. Is the number of arguments incorrect or is the semicolon in a/0 unwanted?
       %    6| a(_) -> error.
      @@ -212,22 +212,22 @@
       my_label              c:pinfo/2                               51
       4> proc_lib:get_label(self()).
       my_label

      Own Id: OTP-18789 Aux Id: PR-7720, PR-8003

    • -callback attributes has been added to modules sys and erl_error.

      Own Id: OTP-18793 Aux Id: PR-7703

    • Several new functions that accept funs have been added to module timer.

      Functions apply_after/2, apply_interval/2, and apply_repeatedly/2 accept a nullary fun as the second argument, while functions apply_after/3, apply_interval/3, and apply_repeatedly/3 accept an n-ary fun as the second and a list of n arguments for the fun as the third argument.

      Own Id: OTP-18808 Aux Id: PR-7649

    • Sigils on string literals have been implemented as per EEP 66, that is: binary and string sigils in verbatim and escape characters variants, as well as a default (vanilla) Sigil. All for ordinary strings and for triple-quoted strings (EEP 64). See Sigils in the Reference Manual.

      Examples:

      1> ~"Björn".
      -<<"Björn"/utf8>>
      +<<"Björn"/utf8>>
       2> ~b"Björn".
      -<<"Björn"/utf8>>
      +<<"Björn"/utf8>>
       3> ~S"\s*(\w+)".
       "\\s*(\\w+)"
       4> ~B"\s*(\w+)".
      -<<"\\s*(\\w+)">>

      Own Id: OTP-18825 Aux Id: OTP-18750, PR-7684

    • Functions shell:default_multiline_prompt/1, shell:inverted_space_prompt/1, and +<<"\\s*(\\w+)">>

    Own Id: OTP-18825 Aux Id: OTP-18750, PR-7684

  • Functions shell:default_multiline_prompt/1, shell:inverted_space_prompt/1, and shell:prompt_width/1 have been exported to help with custom prompt implementations.

    Own Id: OTP-18834 Aux Id: PR-7675, PR-7816

  • The shell now pages long output from the documentation help command (h(Module)), auto completions and the search command.

    Own Id: OTP-18846 Aux Id: PR-7845

  • The M-h hotkey (Alt/Option-h) now outputs help for the module or function directly before the cursor.

    Own Id: OTP-18847 Aux Id: PR-7846

  • Added support for adding a custom code formatter that formats your multi-line shell commands in your preferred formatting on submission. See shell:format_shell_func/ and shell:erl_pp_format_func/1.

    Own Id: OTP-18848 Aux Id: PR-7847

  • Added shell functions for viewing, forgetting and saving locally defined functions, types and records.

    Own Id: OTP-18852 Aux Id: PR-7844

  • Added string:jaro_similarity/2, which can be used to calculate the similarity between two strings.

    Own Id: OTP-18865 Aux Id: PR-7879

  • The new function ets:update_element/4 is similar to ets:update_element/3, but takes a default tuple as the fourth argument, which will be inserted if no previous record with that key exists.

    Own Id: OTP-18870 Aux Id: PR-7857

  • Added functions to retrieve the next higher or lower key/element from gb_trees and gb_sets, as well as returning iterators that start at given keys/elements.

    Own Id: OTP-18874 Aux Id: PR-7745

  • When the shell built-in function c/1,2 is used to re-compile a module, the current working directory of the original compilation is now added to the include path.

    Own Id: OTP-18908 Aux Id: PR-7957

  • The timer module now uses a private table for its internal state, slightly improving its performance.

    Own Id: OTP-18914 Aux Id: PR-7973

  • EEP-59 - Documentation Attributes has been implemented.

    Documentation attributes can be used to document functions, types, callbacks, and modules. The keyword -moduledoc "Documentation here". is used to document modules, while -doc "Documentation here". can be used on top of functions, types, and callbacks to document them, respectively.

    • Types, callbacks, and function documentation can be set to hidden either via -doc false or -doc hidden. When documentation attributes mark a type as hidden, they will not be part of the documentation.

    • The documentation from moduledoc and doc gets added by default to the binary beam file, following the format of EEP-48.

    • Using the compiler flag warn_missing_doc will raise a warning when -doc attributes are missing in exported functions, types, and callbacks.

    • Using the compiler flag warn_missing_spec_documented will raise a warning when -spec attributes are missing in documented functions, types, and callbacks.

    • moduledocs and docs may refer to external files to be embedded, such as -doc {file, "README.md"}., which refers to the file README.md found in the current working directory.

    • The compiler warns about exported functions whose specs refer to hidden types. Thus, there will be warnings when a hidden type (meaning, the type is not part of the documentation) gets used in an exported function.

    Own Id: OTP-18916 Aux Id: PR-7936

  • New ets functions ets:first_lookup/1, ets:next_lookup/2, ets:prev_lookup/2 and ets:last_lookup/1. Example: ets:next_lookup/1 is equivalent to ets:next/2 followed by ets:lookup/2 with the next key. The new combined functions are more efficient and with guaranteed atomicity.

    Own Id: OTP-18923 Aux Id: PR-6791

  • The maybe expression is now enabled by default.

    To use maybe as an atom, it needs to be single-quoted. Alternatively, the maybe expression can be disabled by disabling the maybe_expr feature. That can be done by placing the following the line at the beginning of an Erlang source file:

    -feature(maybe_expr, disable).

    Another way to disable the maybe_expr feature is by passing the -disable-feature option to erlc:

    erlc -disable-feature maybe_expr some_file.erl

    Own Id: OTP-18944 Aux Id: PR-8067

  • The compiler will now raise a warning when updating record/map literals. As an example, consider this module:

    -module(t).
    --export([f/0]).
    --record(r, {a,b,c}).
    +spec attributes are missing in documented functions, types, and callbacks.

  • moduledocs and docs may refer to external files to be embedded, such as -doc {file, "README.md"}., which refers to the file README.md found in the current working directory.

  • The compiler warns about exported functions whose specs refer to hidden types. Thus, there will be warnings when a hidden type (meaning, the type is not part of the documentation) gets used in an exported function.

  • Own Id: OTP-18916 Aux Id: PR-7936

  • New ets functions ets:first_lookup/1, ets:next_lookup/2, ets:prev_lookup/2 and ets:last_lookup/1. Example: ets:next_lookup/1 is equivalent to ets:next/2 followed by ets:lookup/2 with the next key. The new combined functions are more efficient and with guaranteed atomicity.

    Own Id: OTP-18923 Aux Id: PR-6791

  • The maybe expression is now enabled by default.

    To use maybe as an atom, it needs to be single-quoted. Alternatively, the maybe expression can be disabled by disabling the maybe_expr feature. That can be done by placing the following the line at the beginning of an Erlang source file:

    -feature(maybe_expr, disable).

    Another way to disable the maybe_expr feature is by passing the -disable-feature option to erlc:

    erlc -disable-feature maybe_expr some_file.erl

    Own Id: OTP-18944 Aux Id: PR-8067

  • The compiler will now raise a warning when updating record/map literals. As an example, consider this module:

    -module(t).
    +-export([f/0]).
    +-record(r, {a,b,c}).
     
    -f() ->
    -    #href_anchor"ss">r{a=1}#r{b=2}.

    The compiler raises the following warning:

    1> c(t).
    +f() ->
    +    #href_anchor"ss">r{a=1}#r{b=2}.

    The compiler raises the following warning:

    1> c(t).
     t.erl:6:12: Warning: expression updates a literal
     %    6|     #r{a=1}#r{b=2}.
     %     |            ^

    Own Id: OTP-18951 Aux Id: PR-8069

  • The documentation has been migrated to use Markdown and ExDoc.

    Own Id: OTP-18955 Aux Id: PR-8026

  • Optimized ets:foldl and ets:foldr to use new ets:next_lookup. Also made them immune against table renaming.

    Own Id: OTP-18993 Aux Id: PR-8048

  • Windows now supports all functions in math.

    Own Id: OTP-19001 Aux Id: PR-8164

  • erl_lint (and by extension the compiler) will now warn for code using deprecated callbacks.

    The only callback currenly deprecated is format_status/2 in gen_server, gen_event and gen_statem.

    You can use nowarn_deprecated_callback to silence the warning.

    Own Id: OTP-19010 Aux Id: PR-8205

  • There is a new module json for encoding and decoding JSON.

    Both encoding and decoding can be customized. Decoding can be done in a SAX-like fashion and handle multiple documents and streams of data.

    Own Id: OTP-19020 Aux Id: PR-8111

  • STDLIB 5.2.3.6

    Fixed Bugs and Malfunctions

    • Fixed bug in ets:update_counter/4 and ets:update_element/4 accepting and inserting a default tuple smaller than the keypos of the table. Such a tuple without a key element would make the table internally inconsistent and might lead to bad behavior at table access, like ERTS runtime crash.

      Now a call to ets:update_counter/4 or ets:update_element/4 will fail with badarg if the key does not exist in the table and the default tuple is too small.

      Own Id: OTP-19962 Aux Id: PR-10616

    • For a function that started with a bracket-only pattern (such as []), the ?FUNCTION_ARITY macro would evaluate to one less than the actual arity.

      Own Id: OTP-19988 Aux Id: GH-10705, PR-10708

    STDLIB 5.2.3.5

    Fixed Bugs and Malfunctions

    • A set of small bugs in sort stability for `lists:sort/1` and `lists:keysort/1` has been fixed. The bug happened for only some, seemingly random, element sequences. Most sorts were stable.

      Sort stability for `lists:sort/1` is only possible to observe when sorting lists with floating point and integer numbers of the same value.

      For `lists:keysort/1` the list had to start with two tuples where the keys or the whole tuples compared equal.

      Own Id: OTP-19673 Aux Id: ERIERL-1240

    STDLIB 5.2.3.4

    Fixed Bugs and Malfunctions

    • It's now possible to write lists:map(fun is_atom/1, []) or lists:map(fun my_func/1, []), in the shell, instead of lists:map(fun erlang:is_atom/1, []) or lists:map(fun shell_default:my_func/1, []).

      Own Id: OTP-19649 Aux Id: GH-9771 PR-9898

    • Properly strip the leading / and drive letter from filepaths when zipping and unzipping archives.

      Thanks to Wander Nauta for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

      Own Id: OTP-19653 Aux Id: CVE-2025-4748 PR-9941

    • A remote shell can now exit by closing the input stream, without terminating the remote node.

      Own Id: OTP-19667 Aux Id: PR-9912

    STDLIB 5.2.3.3

    Fixed Bugs and Malfunctions

    • Fixed an error in uri_string:percent_decode spec

      Own Id: OTP-19380 Aux Id: GH-8755

    STDLIB 5.2.3.2

    Fixed Bugs and Malfunctions

    • With this change, shutdown procedure handles a race condition between supervisor executing a shutdown and child process termination from other reason.

      Own Id: OTP-19256 Aux Id: PR-8780

    • With this change, uri_string:normalize assumes empty path (do not crash) when no path is provided in the URI map.

      Own Id: OTP-19266 Aux Id: ERIERL-1127, PR-8890

    STDLIB 5.2.3.1

    Fixed Bugs and Malfunctions

    • Fixed a bug that caused the shell completion to crash when keyword and tuple appeared on the same line.

      Own Id: OTP-19157 Aux Id: PR-8638

    STDLIB 5.2.3

    Fixed Bugs and Malfunctions

    • Fix shell expansion of -type a() :: $a. in the erlang shell.

      Own Id: OTP-19062

    • Fix the shell Job Control Mode to not crash when typing TAB or CTRL+R.

      Own Id: OTP-19072 Aux Id: PR-8391

    STDLIB 5.2.2

    Fixed Bugs and Malfunctions

    • Attempting to use the maybe construct in a macro argument could crash the compiler.

      Own Id: OTP-19031 Aux Id: GH-8268

    STDLIB 5.2.1

    Fixed Bugs and Malfunctions

    • The help texts shown by argparse will now display sub-command arguments in the correct order.

      Own Id: OTP-18900 Aux Id: PR-7945, GH-7934

    • Clarified the argparse documentation regarding the user-defined help template.

      Own Id: OTP-18937

    • Fix shell expansion to not crash when expanding invalid using invalid atoms.

      Own Id: OTP-18953 Aux Id: GH-8016 PR-8075

    STDLIB 5.2

    Fixed Bugs and Malfunctions

    • Make shell_docs correctly trim the newline at the end of code blocks.

      Own Id: OTP-18777 Aux Id: PR-7663

    • Replaced unintentional Erlang Public License 1.1 headers in some files with /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/orddict.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1551)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/orddict.html 2026-08-21 04:00:29.826362480 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/orddict.html 2026-08-21 04:00:29.826362480 +0000 @@ -101,13 +101,13 @@ as different if they do not match (=:=), this module considers two keys as different if and only if they do not compare equal (==).

      Notes

      Functions append/3 and append_list/3 are included so that keyed values can be stored in a list accumulator, for -example:

      > D0 = orddict:new(),
      -  D1 = orddict:store(files, [], D0),
      -  D2 = orddict:append(files, f1, D1),
      -  D3 = orddict:append(files, f2, D2),
      -  D4 = orddict:append(files, f3, D3),
      -  orddict:fetch(files, D4).
      -[f1,f2,f3]

      This saves the trouble of first fetching a keyed value, appending a new value to +example:

      > D0 = orddict:new(),
      +  D1 = orddict:store(files, [], D0),
      +  D2 = orddict:append(files, f1, D1),
      +  D3 = orddict:append(files, f2, D2),
      +  D4 = orddict:append(files, f3, D3),
      +  orddict:fetch(files, D4).
      +[f1,f2,f3]

      This saves the trouble of first fetching a keyed value, appending a new value to the list of stored values, and storing the result.

      Function fetch/2 is to be used if the key is known to be in the dictionary, otherwise function find/2.

      See Also

      dict, gb_trees

      @@ -490,16 +490,16 @@

      Appends a new Value to the current list of values associated with Key. An exception is generated if the initial value associated with Key is not a list -of values.

      See also section Notes.

      Example 1:

      1> OrdDict1 = orddict:from_list([{x, []}]).
      -[{x,[]}]
      -2> OrdDict2 = orddict:append(x, 1, OrdDict1).
      -[{x,[1]}]
      -3> OrdDict3 = orddict:append(x, 2, OrdDict2).
      -[{x,[1,2]}]
      -4> orddict:append(y, 3, OrdDict3).
      -[{x,[1,2]},{y,[3]}]

      Example 2:

      1> OrdDict1 = orddict:from_list([{a, no_list}]).
      -[{a,no_list}]
      -2> orddict:append(a, 1, OrdDict1).
      +of values.

      See also section Notes.

      Example 1:

      1> OrdDict1 = orddict:from_list([{x, []}]).
      +[{x,[]}]
      +2> OrdDict2 = orddict:append(x, 1, OrdDict1).
      +[{x,[1]}]
      +3> OrdDict3 = orddict:append(x, 2, OrdDict2).
      +[{x,[1,2]}]
      +4> orddict:append(y, 3, OrdDict3).
      +[{x,[1,2]},{y,[3]}]

      Example 2:

      1> OrdDict1 = orddict:from_list([{a, no_list}]).
      +[{a,no_list}]
      +2> orddict:append(a, 1, OrdDict1).
       ** exception error: bad argument
            in operator  ++/2
               called as no_list ++ [1]
      @@ -536,12 +536,12 @@

      Appends a list of values ValList to the current list of values associated with Key. An exception is generated if the initial value associated with Key is -not a list of values.

      See also section Notes.

      Example:

      1> OrdDict1 = orddict:from_list([{x, []}]).
      -[{x,[]}]
      -2> OrdDict2 = orddict:append_list(x, [1,2], OrdDict1).
      -[{x,[1,2]}]
      -3> OrdDict3 = orddict:append_list(y, [3,4], OrdDict2).
      -[{x,[1,2]},{y,[3,4]}]
      +not a list of values.

      See also section Notes.

      Example:

      1> OrdDict1 = orddict:from_list([{x, []}]).
      +[{x,[]}]
      +2> OrdDict2 = orddict:append_list(x, [1,2], OrdDict1).
      +[{x,[1,2]}]
      +3> OrdDict3 = orddict:append_list(y, [3,4], OrdDict2).
      +[{x,[1,2]},{y,[3,4]}]
      @@ -570,10 +570,10 @@ -

      Erases all items with a specified key from a dictionary.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:erase(a, OrdDict1).
      -[{b,2}]
      +

      Erases all items with a specified key from a dictionary.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:erase(a, OrdDict1).
      +[{b,2}]
      @@ -603,11 +603,11 @@

      Returns the value associated with Key in dictionary Orddict. This function assumes that the Key is present in the dictionary. An exception is generated -if Key is not in the dictionary.

      See also section Notes.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:fetch(a, OrdDict1).
      +if Key is not in the dictionary.

      See also section Notes.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:fetch(a, OrdDict1).
       1
      -3> orddict:fetch(missing, OrdDict1).
      +3> orddict:fetch(missing, OrdDict1).
       ** exception error: no function clause matching orddict:fetch(missing,[])
      @@ -636,10 +636,10 @@ -

      Returns a list of all keys in a dictionary.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:fetch_keys(OrdDict1).
      -[a,b]
      +

      Returns a list of all keys in a dictionary.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:fetch_keys(OrdDict1).
      +[a,b]
      @@ -672,10 +672,10 @@

      Orddict2 is a dictionary of all keys and values in Orddict1 for which -Pred(Key, Value) is true.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:filter(fun (K, V) -> V > 1 end, OrdDict1).
      -[{b,2}]
      +Pred(Key, Value) is true.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:filter(fun (K, V) -> V > 1 end, OrdDict1).
      +[{b,2}]
      @@ -705,11 +705,11 @@

      Searches for a key in a dictionary. Returns {ok, Value}, where Value is the value associated with Key, or error if the key is not present in the -dictionary.

      See also section Notes.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:find(a, OrdDict1).
      -{ok,1}
      -3> orddict:find(c, OrdDict1).
      +dictionary.

      See also section Notes.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:find(a, OrdDict1).
      +{ok,1}
      +3> orddict:find(c, OrdDict1).
       error
      @@ -747,10 +747,10 @@

      Calls Fun on successive keys and values of Orddict together with an extra argument Acc (short for accumulator). Fun must return a new accumulator that -is passed to the next call. Acc0 is returned if the list is empty.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:fold(fun (K, V, Acc) -> [{K, V+100} | Acc] end, [], OrdDict1).
      -[{b,102},{a,101}]
      +is passed to the next call. Acc0 is returned if the list is empty.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:fold(fun (K, V, Acc) -> [{K, V+100} | Acc] end, [], OrdDict1).
      +[{b,102},{a,101}]
      @@ -869,10 +869,10 @@

      Calls Fun on successive keys and values of Orddict1 to return a new value -for each key.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:map(fun (_K, V) -> V + 100 end, OrdDict1).
      -[{a,101},{b,102}]
      +for each key.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:map(fun (_K, V) -> V + 100 end, OrdDict1).
      +[{a,101},{b,102}]
      @@ -908,15 +908,15 @@

      Merges two dictionaries, Orddict1 and Orddict2, to create a new dictionary. All the Key-Value pairs from both dictionaries are included in the new dictionary.

      If a key occurs in both dictionaries, Fun is called with the key -and both values to return a new value.

      merge/3 can be defined as follows, but is faster:

      merge(Fun, D1, D2) ->
      -    fold(fun (K, V1, D) ->
      -                 update(K, fun (V2) -> Fun(K, V1, V2) end, V1, D)
      -         end, D2, D1).

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> OrdDict2 = orddict:from_list([{b, 7}, {c, 8}]).
      -[{b,7},{c,8}]
      -3> orddict:merge(fun (K, V1, V2) -> V1 * V2 end, OrdDict1, OrdDict2).
      -[{a,1},{b,14},{c,8}]
      +and both values to return a new value.

      merge/3 can be defined as follows, but is faster:

      merge(Fun, D1, D2) ->
      +    fold(fun (K, V1, D) ->
      +                 update(K, fun (V2) -> Fun(K, V1, V2) end, V1, D)
      +         end, D2, D1).

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> OrdDict2 = orddict:from_list([{b, 7}, {c, 8}]).
      +[{b,7},{c,8}]
      +3> orddict:merge(fun (K, V1, V2) -> V1 * V2 end, OrdDict1, OrdDict2).
      +[{a,1},{b,14},{c,8}]
      /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ordsets.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1508)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ordsets.html 2026-08-21 04:00:29.855362669 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/ordsets.html 2026-08-21 04:00:29.855362669 +0000 @@ -429,14 +429,14 @@ -

      Returns a new ordered set formed from Ordset1 with Element inserted.

      Examples

      1> S0 = ordsets:new().
      -[]
      -2> S1 = ordsets:add_element(7, S0).
      -[7]
      -3> S2 = ordsets:add_element(42, S1).
      -[7,42]
      -4> ordsets:add_element(42, S2).
      -[7,42]
      +

      Returns a new ordered set formed from Ordset1 with Element inserted.

      Examples

      1> S0 = ordsets:new().
      +[]
      +2> S1 = ordsets:add_element(7, S0).
      +[7]
      +3> S2 = ordsets:add_element(42, S1).
      +[7,42]
      +4> ordsets:add_element(42, S2).
      +[7,42]
      @@ -465,11 +465,11 @@ -

      Returns a copy of Ordset1 with Element removed.

      Examples

      1> S = ordsets:from_list([a,b,c]).
      -2> ordsets:del_element(c, S).
      -[a,b]
      -3> ordsets:del_element(x, S).
      -[a,b,c]
      +

      Returns a copy of Ordset1 with Element removed.

      Examples

      1> S = ordsets:from_list([a,b,c]).
      +2> ordsets:del_element(c, S).
      +[a,b]
      +3> ordsets:del_element(x, S).
      +[a,b,c]
      @@ -499,10 +499,10 @@ -

      Filters elements in Ordset1 using predicate function Pred.

      Examples

      1> S = ordsets:from_list([1,2,3,4,5,6,7]).
      -2> IsEven = fun(N) -> N rem 2 =:= 0 end.
      -3> ordsets:filter(IsEven, S).
      -[2,4,6]
      +

      Filters elements in Ordset1 using predicate function Pred.

      Examples

      1> S = ordsets:from_list([1,2,3,4,5,6,7]).
      +2> IsEven = fun(N) -> N rem 2 =:= 0 end.
      +3> ordsets:filter(IsEven, S).
      +[2,4,6]
      @@ -539,16 +539,16 @@

      Calls Fun(Elem) for each Elem of Ordset1 to update or remove elements from Ordset1.

      Fun/1 must return either a Boolean or a tuple {true, Value}. The function returns the set of elements for which Fun returns a new -value, with true being equivalent to {true, Elem}.

      ordsets:filtermap/2 behaves as if it were defined as follows:

      filtermap(Fun, Ordset1) ->
      -    ordsets:from_list(lists:filtermap(Fun, Ordset1)).

      Examples

      1> S = ordsets:from_list([2,4,5,6,8,9])
      -2> F = fun(X) ->
      +value, with true being equivalent to {true, Elem}.

      ordsets:filtermap/2 behaves as if it were defined as follows:

      filtermap(Fun, Ordset1) ->
      +    ordsets:from_list(lists:filtermap(Fun, Ordset1)).

      Examples

      1> S = ordsets:from_list([2,4,5,6,8,9])
      +2> F = fun(X) ->
                  case X rem 2 of
      -               0 -> {true, X div 2};
      +               0 -> {true, X div 2};
                      1 -> false
                  end
               end.
      -3> ordsets:filtermap(F, S).
      -[1,2,3,4]
      +3>
      ordsets:filtermap(F, S). +[1,2,3,4]
      @@ -582,9 +582,9 @@

      Folds Function over every element in Ordset and returns the final value of -the accumulator.

      Examples

      1> S = ordsets:from_list([1,2,3,4]).
      +the accumulator.

      Examples

      1> S = ordsets:from_list([1,2,3,4]).
       2> Plus = fun erlang:'+'/2.
      -3> ordsets:fold(Plus, 0, S).
      +3> ordsets:fold(Plus, 0, S).
       10
      @@ -613,8 +613,8 @@ -

      Returns an ordered set of the elements in List.

      Examples

      1> ordsets:from_list([a,b,a,b,b,c]).
      -[a,b,c]
      +

      Returns an ordered set of the elements in List.

      Examples

      1> ordsets:from_list([a,b,a,b,b,c]).
      +[a,b,c]
      @@ -643,15 +643,15 @@

      Returns the intersection of the non-empty list of sets.

      The intersection of multiple sets is a new set that contains only the -elements that are present in all sets.

      Examples

      1> S0 = ordsets:from_list([a,b,c,d]).
      -2> S1 = ordsets:from_list([d,e,f]).
      -3> S2 = ordsets:from_list([q,r])
      -4> Sets = [S0, S1, S2].
      -5> ordsets:intersection([S0, S1, S2]).
      -[]
      -6> ordsets:intersection([S0, S1]).
      -[d]
      -7> ordsets:intersection([]).
      +elements that are present in all sets.

      Examples

      1> S0 = ordsets:from_list([a,b,c,d]).
      +2> S1 = ordsets:from_list([d,e,f]).
      +3> S2 = ordsets:from_list([q,r])
      +4> Sets = [S0, S1, S2].
      +5> ordsets:intersection([S0, S1, S2]).
      +[]
      +6> ordsets:intersection([S0, S1]).
      +[d]
      +7> ordsets:intersection([]).
       ** exception error: no function clause matching ordsets:intersection([])
      @@ -682,13 +682,13 @@

      Returns the intersection of Ordset1 and Ordset2.

      The intersection of two sets is a new set that contains only the -elements that are present in both sets.

      Examples

      1> S0 = ordsets:from_list([a,b,c,d]).
      -2> S1 = ordsets:from_list([c,d,e,f]).
      -3> S2 = ordsets:from_list([q,r]).
      -4> ordsets:intersection(S0, S1).
      -[c,d]
      -5> ordsets:intersection(S1, S2).
      -[]
      +elements that are present in both sets.

      Examples

      1> S0 = ordsets:from_list([a,b,c,d]).
      +2> S1 = ordsets:from_list([c,d,e,f]).
      +3> S2 = ordsets:from_list([q,r]).
      +4> ordsets:intersection(S0, S1).
      +[c,d]
      +5> ordsets:intersection(S1, S2).
      +[]
      @@ -717,12 +717,12 @@

      Returns true if Ordset1 and Ordset2 are disjoint; otherwise, -returns false.

      Two sets are disjoint if they have no elements in common.

      This function is equivalent to ordsets:intersection(Ordset1, Ordset2) =:= [], but faster.

      Examples

      1> S0 = ordsets:from_list([a,b,c,d]).
      -2> S1 = ordsets:from_list([d,e,f]).
      -3> S2 = ordsets:from_list([q,r])
      -4> ordsets:is_disjoint(S0, S1).
      +returns false.

      Two sets are disjoint if they have no elements in common.

      This function is equivalent to ordsets:intersection(Ordset1, Ordset2) =:= [], but faster.

      Examples

      1> S0 = ordsets:from_list([a,b,c,d]).
      +2> S1 = ordsets:from_list([d,e,f]).
      +3> S2 = ordsets:from_list([q,r])
      +4> ordsets:is_disjoint(S0, S1).
       false
      -5> ordsets:is_disjoint(S1, S2).
      +5> ordsets:is_disjoint(S1, S2).
       true
      @@ -751,10 +751,10 @@ -

      Returns true if Element is an element of Ordset; otherwise, returns false.

      Examples

      1> S = ordsets:from_list([a,b,c]).
      -2> ordsets:is_element(42, S).
      +

      Returns true if Element is an element of Ordset; otherwise, returns false.

      Examples

      1> S = ordsets:from_list([a,b,c]).
      +2> ordsets:is_element(42, S).
       false
      -3> ordsets:is_element(b, S).
      +3> ordsets:is_element(b, S).
       true
      @@ -785,9 +785,9 @@ -

      Returns true if Ordset is an empty set; otherwise, returns false.

      Examples

      1> ordsets:is_empty(ordsets:new()).
      +

      Returns true if Ordset is an empty set; otherwise, returns false.

      Examples

      1> ordsets:is_empty(ordsets:new()).
       true
      -2> ordsets:is_empty(ordsets:from_list([1])).
      +2> ordsets:is_empty(ordsets:from_list([1])).
       false
      @@ -819,11 +819,11 @@

      Returns true if Ordset1 and Ordset2 are equal, that is, if every element -of one set is also a member of the other set; otherwise, returns false.

      Examples

      1> Empty = ordsets:new().
      -2> S = ordsets:from_list([a,b]).
      -3> ordsets:is_equal(S, S)
      /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/peer.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1109))
      --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/peer.html	2026-08-21 04:00:29.886362871 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/peer.html	2026-08-21 04:00:29.886362871 +0000
      @@ -120,127 +120,127 @@
       manual analysis. If the test case fails, the CRASH REPORT contains these
       arguments
    • multiple test cases can run concurrently speeding up overall testing process, peer node names are unique even when there are multiple instances of the same -test suite running in parallel
    -module(my_SUITE).
    --behaviour(ct_suite).
    --export([all/0, groups/0]).
    --export([basic/1, args/1, named/1, restart_node/1, multi_node/1]).
    +test suite running in parallel
    -module(my_SUITE).
    +-behaviour(ct_suite).
    +-export([all/0, groups/0]).
    +-export([basic/1, args/1, named/1, restart_node/1, multi_node/1]).
     
    --include_lib("common_test/include/ct.hrl").
    +-include_lib("common_test/include/ct.hrl").
     
    -groups() ->
    -    [{quick, [parallel],
    -        [basic, args, named, restart_node, multi_node]}].
    +groups() ->
    +    [{quick, [parallel],
    +        [basic, args, named, restart_node, multi_node]}].
     
    -all() ->
    -    [{group, quick}].
    +all() ->
    +    [{group, quick}].
     
    -basic(Config) when is_list(Config) ->
    -    {ok, Peer, _Node} = ?CT_PEER(),
    -    peer:stop(Peer).
    +basic(Config) when is_list(Config) ->
    +    {ok, Peer, _Node} = ?CT_PEER(),
    +    peer:stop(Peer).
     
    -args(Config) when is_list(Config) ->
    +args(Config) when is_list(Config) ->
         %% specify additional arguments to the new node
    -    {ok, Peer, _Node} = ?CT_PEER(["-emu_flavor", "smp"]),
    -    peer:stop(Peer).
    +    {ok, Peer, _Node} = ?CT_PEER(["-emu_flavor", "smp"]),
    +    peer:stop(Peer).
     
    -named(Config) when is_list(Config) ->
    +named(Config) when is_list(Config) ->
         %% pass test case name down to function starting nodes
    -    Peer = start_node_impl(named_test),
    -    peer:stop(Peer).
    +    Peer = start_node_impl(named_test),
    +    peer:stop(Peer).
     
    -start_node_impl(ActualTestCase) ->
    -    {ok, Peer, Node} = ?CT_PEER(#{name => ?CT_PEER_NAME(ActualTestCase)}),
    +start_node_impl(ActualTestCase) ->
    +    {ok, Peer, Node} = ?CT_PEER(#{name => ?CT_PEER_NAME(ActualTestCase)}),
         %% extra setup needed for multiple test cases
    -    ok = rpc:call(Node, application, set_env, [kernel, key, value]),
    +    ok = rpc:call(Node, application, set_env, [kernel, key, value]),
         Peer.
     
    -restart_node(Config) when is_list(Config) ->
    -    Name = ?CT_PEER_NAME(),
    -    {ok, Peer, Node} = ?CT_PEER(#{name => Name}),
    -    peer:stop(Peer),
    +restart_node(Config) when is_list(Config) ->
    +    Name = ?CT_PEER_NAME(),
    +    {ok, Peer, Node} = ?CT_PEER(#{name => Name}),
    +    peer:stop(Peer),
         %% restart the node with the same name as before
    -    {ok, Peer2, Node} = ?CT_PEER(#{name => Name, args => ["+fnl"]}),
    -    peer:stop(Peer2).

    The next example demonstrates how to start multiple nodes concurrently:

    multi_node(Config) when is_list(Config) ->
    -    Peers = [?CT_PEER(#{wait_boot => {self(), tag}})
    -        || _ <- lists:seq(1, 4)],
    +    {ok, Peer2, Node} = ?CT_PEER(#{name => Name, args => ["+fnl"]}),
    +    peer:stop(Peer2).

    The next example demonstrates how to start multiple nodes concurrently:

    multi_node(Config) when is_list(Config) ->
    +    Peers = [?CT_PEER(#{wait_boot => {self(), tag}})
    +        || _ <- lists:seq(1, 4)],
         %% wait for all nodes to complete boot process, get their names:
    -    _Nodes = [receive {tag, {started, Node, Peer}} -> Node end
    -        || {ok, Peer} <- Peers],
    -    [peer:stop(Peer) || {ok, Peer} <- Peers].

    Start a peer on a different host. Requires ssh key-based authentication set -up, allowing "another_host" connection without password prompt.

    Ssh = os:find_executable("ssh"),
    -peer:start_link(#{exec => {Ssh, ["another_host", "erl"]},
    -    connection => standard_io}),

    The following Common Test case demonstrates Docker integration, starting two + _Nodes = [receive {tag, {started, Node, Peer}} -> Node end + || {ok, Peer} <- Peers], + [peer:stop(Peer) || {ok, Peer} <- Peers].

    Start a peer on a different host. Requires ssh key-based authentication set +up, allowing "another_host" connection without password prompt.

    Ssh = os:find_executable("ssh"),
    +peer:start_link(#{exec => {Ssh, ["another_host", "erl"]},
    +    connection => standard_io}),

    The following Common Test case demonstrates Docker integration, starting two containers with hostnames "one" and "two". In this example Erlang nodes running -inside containers form an Erlang cluster.

    docker(Config) when is_list(Config) ->
    -    Docker = os:find_executable("docker"),
    -    PrivDir = proplists:get_value(priv_dir, Config),
    -    build_release(PrivDir),
    -    build_image(PrivDir),
    +inside containers form an Erlang cluster.

    docker(Config) when is_list(Config) ->
    +    Docker = os:find_executable("docker"),
    +    PrivDir = proplists:get_value(priv_dir, Config),
    +    build_release(PrivDir),
    +    build_image(PrivDir),
     
         %% start two Docker containers
    -    {ok, Peer, Node} = peer:start_link(#{name => lambda,
    +    {ok, Peer, Node} = peer:start_link(#{name => lambda,
             connection => standard_io,
    -        exec => {Docker, ["run", "-h", "one", "-i", "lambda"]}}),
    -    {ok, Peer2, Node2} = peer:start_link(#{name => lambda,
    +        exec => {Docker, ["run", "-h", "one", "-i", "lambda"]}}),
    +    {ok, Peer2, Node2} = peer:start_link(#{name => lambda,
             connection => standard_io,
    -        exec => {Docker, ["run", "-h", "two", "-i", "lambda"]}}),
    +        exec => {Docker, ["run", "-h", "two", "-i", "lambda"]}}),
     
         %% find IP address of the second node using alternative connection RPC
    -    {ok, Ips} = peer:call(Peer2, inet, getifaddrs, []),
    -    {"eth0", Eth0} = lists:keyfind("eth0", 1, Ips),
    -    {addr, Ip} = lists:keyfind(addr, 1, Eth0),
    +    {ok, Ips} = peer:call(Peer2, inet, getifaddrs, []),
    +    {"eth0", Eth0} = lists:keyfind("eth0", 1, Ips),
    +    {addr, Ip} = lists:keyfind(addr, 1, Eth0),
     
         %% make first node to discover second one
    -    ok = peer:call(Peer, inet_db, set_lookup, [[file]]),
    -    ok = peer:call(Peer, inet_db, add_host, [Ip, ["two"]]),
    +    ok = peer:call(Peer, inet_db, set_lookup, [[file]]),
    +    ok = peer:call(Peer, inet_db, add_host, [Ip, ["two"]]),
     
         %% join a cluster
    -    true = peer:call(Peer, net_kernel, connect_node, [Node2]),
    +    true = peer:call(Peer, net_kernel, connect_node, [Node2]),
         %% verify that second peer node has only the first node visible
    -    [Node] = peer:call(Peer2, erlang, nodes, []),
    +    [Node] = peer:call(Peer2, erlang, nodes, []),
     
         %% stop peers, causing containers to also stop
    -    peer:stop(Peer2),
    -    peer:stop(Peer).
    +    peer:stop(Peer2),
    +    peer:stop(Peer).
     
    -build_release(Dir) ->
    +build_release(Dir) ->
         %% load sasl.app file, otherwise application:get_key will fail
    -    application:load(sasl),
    +    application:load(sasl),
         %% create *.rel - release file
    -    RelFile = filename:join(Dir, "lambda.rel"),
    -    Release = {release, {"lambda", "1.0.0"},
    -        {erts, erlang:system_info(version)},
    -        [{App, begin {ok, Vsn} = application:get_key(App, vsn), Vsn end}
    -            || App <- [kernel, stdlib, sasl]]},
    -    ok = file:write_file(RelFile, list_to_binary(lists:flatten(
    -        io_lib:format("~tp.", [Release])))),
    -    RelFileNoExt = filename:join(Dir, "lambda"),
    +    RelFile = filename:join(Dir, "lambda.rel"),
    +    Release = {release, {"lambda", "1.0.0"},
    +        {erts, erlang:system_info(version)},
    +        [{App, begin {ok, Vsn} = application:get_key(App, vsn), Vsn end}
    +            || App <- [kernel, stdlib, sasl]]},
    +    ok = file:write_file(RelFile, list_to_binary(lists:flatten(
    +        io_lib:format("~tp.", [Release])))),
    +    RelFileNoExt = filename:join(Dir, "lambda"),
     
         %% create boot script
    -    {ok, systools_make, []} = systools:make_script(RelFileNoExt,
    -        [silent, {outdir, Dir}]),
    +    {ok, systools_make, []} = systools:make_script(RelFileNoExt,
    +        [silent, {outdir, Dir}]),
         %% package release into *.tar.gz
    -    ok = systools:make_tar(RelFileNoExt, [{erts, code:root_dir()}]).
    +    ok = systools:make_tar(RelFileNoExt, [{erts, code:root_dir()}]).
     
    -build_image(Dir) ->
    +build_image(Dir) ->
         %% Create Dockerfile example, working only for Ubuntu 20.04
         %% Expose port 4445, and make Erlang distribution to listen
         %%  on this port, and connect to it without EPMD
         %% Set cookie on both nodes to be the same.
    -    BuildScript = filename:join(Dir, "Dockerfile"),
    +    BuildScript = filename:join(Dir, "Dockerfile"),
         Dockerfile =
           "FROM ubuntu:20.04 as runner\n"
           "EXPOSE 4445\n"
           "WORKDIR /opt/lambda\n"
           "COPY lambda.tar.gz /tmp\n"
           "RUN tar -zxvf /tmp/lambda.tar.gz -C /opt/lambda\n"
    -      "ENTRYPOINT [\"/opt/lambda/erts-" ++ erlang:system_info(version) ++
    +      "ENTRYPOINT [\"/opt/lambda/erts-" ++ erlang:system_info(version) ++
           "/bin/dyn_erl\", \"-boot\", \"/opt/lambda/releases/1.0.0/start\","
           " \"-kernel\", \"inet_dist_listen_min\", \"4445\","
           " \"-erl_epmd_port\", \"4445\","
           " \"-setcookie\", \"secret\"]\n",
    -    ok = file:write_file(BuildScript, Dockerfile),
    -    os:cmd("docker build -t lambda " ++ Dir).
    +
    ok = file:write_file(BuildScript, Dockerfile), + os:cmd("docker build -t lambda " ++ Dir).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/proc_lib.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/proc_lib.html 2026-08-21 04:00:29.918363079 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/proc_lib.html 2026-08-21 04:00:29.918363079 +0000 @@ -944,21 +944,21 @@ failed. When doing so the start function can return before the failing process has exited, which may block VM resources required for a new start attempt to succeed. Use init_fail/2,3 for that purpose.

    The following example illustrates how this function and proc_lib:start_link/3 -are used:

    -module(my_proc).
    --export([start_link/0]).
    --export([init/1]).
    +are used:

    -module(my_proc).
    +-export([start_link/0]).
    +-export([init/1]).
     
    -start_link() ->
    -    proc_lib:start_link(my_proc, init, [self()]).
    +start_link() ->
    +    proc_lib:start_link(my_proc, init, [self()]).
     
    -init(Parent) ->
    -    case do_initialization() of
    +init(Parent) ->
    +    case do_initialization() of
             ok ->
    -            proc_lib:init_ack(Parent, {ok, self()});
    -        {error, Reason} ->
    -            exit(Reason)
    +            proc_lib:init_ack(Parent, {ok, self()});
    +        {error, Reason} ->
    +            exit(Reason)
         end,
    -    loop().
    +    loop().
     
     ...
    @@ -1031,21 +1031,21 @@ started process, the start function returns an error tuple when the started process exits, or when the start function time-out (if used) has passed, see start/3,4,5.

    The following example illustrates how this function and proc_lib:start_link/3 -can be used:

    -module(my_proc).
    --export([start_link/0]).
    --export([init/1]).
    +can be used:

    -module(my_proc).
    +-export([start_link/0]).
    +-export([init/1]).
     
    -start_link() ->
    -    proc_lib:start_link(my_proc, init, [self()]).
    +start_link() ->
    +    proc_lib:start_link(my_proc, init, [self()]).
     
    -init(Parent) ->
    -    case do_initialization() of
    +init(Parent) ->
    +    case do_initialization() of
             ok ->
    -            proc_lib:init_ack(Parent, {ok, self()});
    -        {error, Reason} = Error ->
    -            proc_lib:init_fail(Parent, Error, {exit, normal})
    +            proc_lib:init_ack(Parent, {ok, self()});
    +        {error, Reason} = Error ->
    +            proc_lib:init_fail(Parent, Error, {exit, normal})
         end,
    -    loop().
    +    loop().
     
     ...
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/proplists.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (3915)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/proplists.html 2026-08-21 04:00:29.946363261 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/proplists.html 2026-08-21 04:00:29.946363261 +0000 @@ -497,7 +497,7 @@

    Similar to get_all_values/2, but each value is wrapped in a list unless it is already itself a list. The resulting list of lists is concatenated. This is -often useful for "incremental" options.

    Example:

    append_values(a, [{a, [1,2]}, {b, 0}, {a, 3}, {c, -1}, {a, [4]}])

    returns:

    [1,2,3,4]
    +often useful for "incremental" options.

    Example:

    append_values(a, [{a, [1,2]}, {b, 0}, {a, 3}, {c, -1}, {a, [4]}])

    returns:

    [1,2,3,4]
    @@ -591,10 +591,10 @@ first entry in ListIn with the same key as Property, and E and Property have equivalent normal forms, then E is replaced with the terms in Expansion, and any following entries with the same key are deleted from -ListIn.

    For example, the following expressions all return [fie, bar, baz, fum]:

    expand([{foo, [bar, baz]}], [fie, foo, fum])
    -expand([{{foo, true}, [bar, baz]}], [fie, foo, fum])
    -expand([{{foo, false}, [bar, baz]}], [fie, {foo, false}, fum])

    However, no expansion is done in the following call because {foo, false} -shadows foo:

    expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])

    Notice that if the original property term is to be preserved in the result when +ListIn.

    For example, the following expressions all return [fie, bar, baz, fum]:

    expand([{foo, [bar, baz]}], [fie, foo, fum])
    +expand([{{foo, true}, [bar, baz]}], [fie, foo, fum])
    +expand([{{foo, false}, [bar, baz]}], [fie, {foo, false}, fum])

    However, no expansion is done in the following call because {foo, false} +shadows foo:

    expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])

    Notice that if the original property term is to be preserved in the result when expanded, it must be included in the expansion list. The inserted terms are not expanded recursively. If Expansions contains more than one property with the same key, only the first occurrence is used.

    See also normalize/2.

    @@ -999,7 +999,7 @@

    Partitions List into a list of sublists and a remainder.

    Lists contains one sublist for each key in Keys, in the corresponding order. The relative order of the elements in each sublist is preserved from the original List. Rest contains the elements in List that are not associated with any of the -specified keys, also with their original relative order preserved.

    Example:

    split([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])

    returns:

    {[[a], [{b, 5}, b],[{c, 2}, {c, 3, 4}]], [{e, 1}, d]}
    +specified keys, also with their original relative order preserved.

    Example:

    split([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])

    returns:

    {[[a], [{b, 5}, b],[{c, 2}, {c, 3, 4}]], [{e, 1}, d]}
    @@ -1122,7 +1122,7 @@ an association of the form Key => Value. Anything else will be silently ignored.

    If the same key appears in List multiple times, the value of the one appearing nearest to the head of List will be in the result map, that is the value that -would be returned by a call to get_value(Key, List).

    Example:

    to_map([a, {b, 1}, {c, 2}, {c, 3}])

    returns:

    #{a => true, b => 1, c => 2}
    +would be returned by a call to get_value(Key, List).

    Example:

    to_map([a, {b, 1}, {c, 2}, {c, 3}])

    returns:

    #{a => true, b => 1, c => 2}
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/qlc.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1468)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/qlc.html 2026-08-21 04:00:29.995363580 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/qlc.html 2026-08-21 04:00:29.996363587 +0000 @@ -214,24 +214,24 @@ If a tuple {finished} exists among the answers to QH, it is returned twice from append/2.

    As another example, consider concatenating the answers to two queries QH1 and QH2 while removing all duplicates. This is accomplished by using option -unique:

    qlc:q([X || X <- qlc:append(QH1, QH2)], {unique, true})

    The cost is substantial: every returned answer is stored in an ETS table. Before +unique:

    qlc:q([X || X <- qlc:append(QH1, QH2)], {unique, true})

    The cost is substantial: every returned answer is stored in an ETS table. Before returning an answer, it is looked up in the ETS table to check if it has already been returned. Without the unique option, all answers to QH1 would be returned followed by all answers to QH2. The unique option keeps the order between the remaining answers.

    If the order of the answers is not important, there is an alternative to the -unique option, namely to sort the answers uniquely:

    qlc:sort(qlc:q([X || X <- qlc:append(QH1, QH2)], {unique, true})).

    This query also removes duplicates but the answers are sorted. If there are many +unique option, namely to sort the answers uniquely:

    qlc:sort(qlc:q([X || X <- qlc:append(QH1, QH2)], {unique, true})).

    This query also removes duplicates but the answers are sorted. If there are many answers, temporary files are used. Notice that to get the first unique answer, all answers must be found and sorted. Both alternatives find duplicates by comparing answers, that is, if A1 and A2 are answers found in that order, then A2 is a removed if A1 == A2.

    To return only a few answers, cursors can be used. The following code returns no -more than five answers using an ETS table for storing the unique answers:

    C = qlc:cursor(qlc:q([X || X <- qlc:append(QH1, QH2)],{unique,true})),
    -R = qlc:next_answers(C, 5),
    -ok = qlc:delete_cursor(C),
    +more than five answers using an ETS table for storing the unique answers:

    C = qlc:cursor(qlc:q([X || X <- qlc:append(QH1, QH2)],{unique,true})),
    +R = qlc:next_answers(C, 5),
    +ok = qlc:delete_cursor(C),
     R.

    QLCs are convenient for stating constraints on data from two or more tables. The -following example does a natural join on two query handles on position 2:

    qlc:q([{X1,X2,X3,Y1} ||
    -          {X1,X2,X3} <- QH1,
    -          {Y1,Y2} <- QH2,
    -          X2 =:= Y2])

    The qlc module evaluates this differently depending on the query handles QH1 +following example does a natural join on two query handles on position 2:

    qlc:q([{X1,X2,X3,Y1} ||
    +          {X1,X2,X3} <- QH1,
    +          {Y1,Y2} <- QH2,
    +          X2 =:= Y2])

    The qlc module evaluates this differently depending on the query handles QH1 and QH2. If, for example, X2 is matched against the key of a QLC table, the lookup join method traverses the objects of QH2 while looking up key values in the table. However, if not X2 or Y2 is matched against the key or an indexed @@ -239,11 +239,11 @@ both sorted on position 2 and next do the join by traversing the objects one by one.

    Option join can be used to force the qlc module to use a certain join method. For the rest of this section it is assumed that the excessively slow -join method called "nested loop" has been chosen:

    qlc:q([{X1,X2,X3,Y1} ||
    -          {X1,X2,X3} <- QH1,
    -          {Y1,Y2} <- QH2,
    -          X2 =:= Y2],
    -      {join, nested_loop})

    In this case the filter is applied to every possible pair of answers to QH1 +join method called "nested loop" has been chosen:

    qlc:q([{X1,X2,X3,Y1} ||
    +          {X1,X2,X3} <- QH1,
    +          {Y1,Y2} <- QH2,
    +          X2 =:= Y2],
    +      {join, nested_loop})

    In this case the filter is applied to every possible pair of answers to QH1 and QH2, one at a time. If there are M answers to QH1 and N answers to QH2, the filter is run M*N times.

    If QH2 is a call to the function for gb_trees, as defined in section Implementing a QLC Table, then @@ -257,7 +257,7 @@ no side effects so that the meaning of the query does not change if QH2 is evaluated only once. One way of caching the answers is to evaluate QH2 first of all and substitute the list of answers for QH2 in the query. Another way is -to use option cache. It is expressed like this:

    QH2' = qlc:q([X || X <- QH2], {cache, ets})

    or only

    QH2' = qlc:q([X || X <- QH2], cache)

    The effect of option cache is that when generator QH2' is run the first +to use option cache. It is expressed like this:

    QH2' = qlc:q([X || X <- QH2], {cache, ets})

    or only

    QH2' = qlc:q([X || X <- QH2], cache)

    The effect of option cache is that when generator QH2' is run the first time, every answer is stored in an ETS table. When the next answer of QH1 is tried, answers to QH2' are copied from the ETS table, which is very fast. As for option unique the cost is a possibly substantial amount of RAM memory.

    Option {cache, list} offers the possibility to store the answers in a list on @@ -273,62 +273,62 @@ tables and lists on all levels of the query. This can be used for testing if caching would improve efficiency at all. If the answer is yes, further testing is needed to pinpoint the generators that are to be cached.

    Implementing a QLC Table

    As an example of how to use function table/2, the implementation of a QLC -table for the gb_trees module is given:

    -module(gb_table).
    +table for the gb_trees module is given:

    -module(gb_table).
     
    --export([table/1]).
    +-export([table/1]).
     
    -table(T) ->
    -    TF = fun() -> qlc_next(gb_trees:next(gb_trees:iterator(T))) end,
    -    InfoFun = fun(num_of_objects) -> gb_trees:size(T);
    -                 (keypos) -> 1;
    -                 (is_sorted_key) -> true;
    -                 (is_unique_objects) -> true;
    -                 (_) -> undefined
    +table(T) ->
    +    TF = fun() -> qlc_next(gb_trees:next(gb_trees:iterator(T))) end,
    +    InfoFun = fun(num_of_objects) -> gb_trees:size(T);
    +                 (keypos) -> 1;
    +                 (is_sorted_key) -> true;
    +                 (is_unique_objects) -> true;
    +                 (_) -> undefined
                   end,
         LookupFun =
    -        fun(1, Ks) ->
    -                lists:flatmap(fun(K) ->
    -                                      case gb_trees:lookup(K, T) of
    -                                          {value, V} -> [{K,V}];
    -                                          none -> []
    +        fun(1, Ks) ->
    +                lists:flatmap(fun(K) ->
    +                                      case gb_trees:lookup(K, T) of
    +                                          {value, V} -> [{K,V}];
    +                                          none -> []
                                           end
    -                              end, Ks)
    +                              end, Ks)
             end,
         FormatFun =
    -        fun({all, NElements, ElementFun}) ->
    -                ValsS = io_lib:format("gb_trees:from_orddict(~w)",
    -                                      [gb_nodes(T, NElements, ElementFun)]),
    -                io_lib:format("gb_table:table(~s)", [ValsS]);
    -           ({lookup, 1, KeyValues, _NElements, ElementFun}) ->
    -                ValsS = io_lib:format("gb_trees:from_orddict(~w)",
    -                                      [gb_nodes(T, infinity, ElementFun)]),
    -                io_lib:format("lists:flatmap(fun(K) -> "
    +        fun({all, NElements, ElementFun}) ->
    +                ValsS = io_lib:format("gb_trees:from_orddict(~w)",
    +                                      [gb_nodes(T, NElements, ElementFun)]),
    +                io_lib:format("gb_table:table(~s)", [ValsS]);
    +           ({lookup, 1, KeyValues, _NElements, ElementFun}) ->
    +                ValsS = io_lib:format("gb_trees:from_orddict(~w)",
    +                                      [gb_nodes(T, infinity, ElementFun)]),
    +                io_lib:format("lists:flatmap(fun(K) -> "
                                   "case gb_trees:lookup(K, ~s) of "
                                   "{value, V} -> [{K,V}];none -> [] end "
                                   "end, ~w)",
    -                              [ValsS, [ElementFun(KV) || KV <- KeyValues]])
    +                              [ValsS, [ElementFun(KV) || KV <- KeyValues]])
             end,
    -    qlc:table(TF, [{info_fun, InfoFun}, {format_fun, FormatFun},
    -                   {lookup_fun, LookupFun},{key_equality,&#href_anchor"p" data-group-id="7468426032-44">}]).
    +    qlc:table(TF, [{info_fun, InfoFun}, {format_fun, FormatFun},
    +                   {lookup_fun, LookupFun},{key_equality,&#href_anchor"p" data-group-id="9449808532-44">}]).
     
    -qlc_next({X, V, S}) ->
    -    [{X,V} | fun() -> qlc_next(gb_trees:next(S)) end];
    -qlc_next(none) ->
    -    [].
    -
    -gb_nodes(T, infinity, ElementFun) ->
    -    gb_nodes(T, -1, ElementFun);
    -gb_nodes(T, NElements, ElementFun) ->
    -    gb_iter(gb_trees:iterator(T), NElements, ElementFun).
    +qlc_next({X, V, S}) ->
    +    [{X,V} | fun() -> qlc_next(gb_trees:next(S)) end];
    +qlc_next(none) ->
    +    [].
    +
    +gb_nodes(T, infinity, ElementFun) ->
    +    gb_nodes(T, -1, ElementFun);
    +gb_nodes(T, NElements, ElementFun) ->
    +    gb_iter(gb_trees:iterator(T), NElements, ElementFun).
     
    -gb_iter(_I, 0, _EFun) ->
    +gb_iter(_I, 0, _EFun) ->
         '...';
    -gb_iter(I0, N, EFun) ->
    -    case gb_trees:next(I0) of
    -        {X, V, I} ->
    -            [EFun({X,V}) | gb_iter(I, N-1, EFun)];
    +gb_iter(I0, N, EFun) ->
    +    case gb_trees:next(I0) of
    +        {X, V, I} ->
    +            [EFun({X,V}) | gb_iter(I, N-1, EFun)];
             none ->
    -            []
    +            []
         end.

    TF is the traversal function. The qlc module requires that there is a way of traversing all objects of the data structure. gb_trees has an iterator function suitable for that purpose. Notice that for each object returned, a new @@ -358,49 +358,49 @@ example, 2 == 2.0 evaluates to true while 2 =:= 2.0 evaluates to false. Normally this is a minor issue, but the qlc module cannot ignore the difference, which affects the user's choice of operators in QLCs.

    If the qlc module at compile time can determine that some constant is free of -integers, it does not matter which one of ==/2 or =:=/2 is used:

    1> E1 = ets:new(t, [set]), % uses =:=/2 for key equality
    -Q1 = qlc:q([K ||
    -{K} <- ets:table(E1),
    -K == 2.71 orelse K == a]),
    -io:format("~s~n", [qlc:info(Q1)]).
    -ets:match_spec_run(
    -       lists:flatmap(fun(V) ->
    -			    ets:lookup(#Ref<0.3098908599.2283929601.256025>,
    -				       V)
    +integers, it does not matter which one of ==/2 or =:=/2 is used:

    1> E1 = ets:new(t, [set]), % uses =:=/2 for key equality
    +Q1 = qlc:q([K ||
    +{K} <- ets:table(E1),
    +K == 2.71 orelse K == a]),
    +io:format("~s~n", [qlc:info(Q1)]).
    +ets:match_spec_run(
    +       lists:flatmap(fun(V) ->
    +			    ets:lookup(#Ref<0.3098908599.2283929601.256025>,
    +				       V)
     		     end,
    -		     [a, 2.71]),
    -       ets:match_spec_compile([{{'$1'}, [], ['$1']}]))

    In the example, operator ==/2 has been handled exactly as =:=/2 would have + [a, 2.71]), + ets:match_spec_compile([{{'$1'}, [], ['$1']}]))

    In the example, operator ==/2 has been handled exactly as =:=/2 would have been handled. However, if it cannot be determined at compile time that some constant is free of integers, and the table uses =:=/2 when comparing keys for equality (see option key_equality), then the qlc module does not try to look up the constant. The reason is that there is in the general case no upper limit on the number of key values that can compare equal -to such a constant; every combination of integers and floats must be looked up:

    2> E2 = ets:new(t, [set]),
    -true = ets:insert(E2, [{{2,2},a},{{2,2.0},b},{{2.0,2},c}]),
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/queue.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1100))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/queue.html	2026-08-21 04:00:30.031363814 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/queue.html	2026-08-21 04:00:30.032363821 +0000
    @@ -685,12 +685,12 @@
     
           
     
    -

    Returns a queue Q2 that is the result of removing the front item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:from_list([1,2,3,4,5]).
    -{[5,4,3],[1,2]}
    -2> Queue = queue:drop(Queue).
    -{[5,4,3],[2]}
    -3> queue:to_list(Queue1).
    -[2,3,4,5]
    +

    Returns a queue Q2 that is the result of removing the front item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:from_list([1,2,3,4,5]).
    +{[5,4,3],[1,2]}
    +2> Queue = queue:drop(Queue).
    +{[5,4,3],[2]}
    +3> queue:to_list(Queue1).
    +[2,3,4,5]
    @@ -718,12 +718,12 @@ -

    Returns a queue Q2 that is the result of removing the rear item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:from_list([1,2,3,4,5]).
    -{[5,4,3],[1,2]}
    -2> Queue = queue:drop_r(Queue).
    -{[4,3],[1,2]}
    -3> queue:to_list(Queue1).
    -[1,2,3,4]
    +

    Returns a queue Q2 that is the result of removing the rear item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:from_list([1,2,3,4,5]).
    +{[5,4,3],[1,2]}
    +2> Queue = queue:drop_r(Queue).
    +{[4,3],[1,2]}
    +3> queue:to_list(Queue1).
    +[1,2,3,4]
    @@ -751,9 +751,9 @@ -

    Returns Item at the front of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> Queue = queue:from_list([1,2,3,4,5]).
    -{[5,4,3],[1,2]}
    -2> 1 == queue:get(Queue).
    +

    Returns Item at the front of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> Queue = queue:from_list([1,2,3,4,5]).
    +{[5,4,3],[1,2]}
    +2> 1 == queue:get(Queue).
     true
    @@ -782,9 +782,9 @@ -

    Returns Item at the rear of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> Queue = queue:from_list([1,2,3,4,5]).
    -{[5,4,3],[1,2]}
    -2> 5 == queue:get_r(Queue).
    +

    Returns Item at the rear of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> Queue = queue:from_list([1,2,3,4,5]).
    +{[5,4,3],[1,2]}
    +2> 5 == queue:get_r(Queue).
     true
    @@ -814,12 +814,12 @@

    Returns tuple {value, Item}, where Item is the front item of Q, or empty -if Q is empty.

    Example 1:

    1> queue:peek(queue:new()).
    +if Q is empty.

    Example 1:

    1> queue:peek(queue:new()).
     empty
    -2> Queue = queue:from_list([1,2,3,4,5]).
    -{[5,4,3],[1,2]}
    -3> queue:peek(Queue).
    -{value, 1}
    +2>
    Queue = queue:from_list([1,2,3,4,5]). +{[5,4,3],[1,2]} +3> queue:peek(Queue). +{value, 1}
    @@ -848,12 +848,12 @@

    Returns tuple {value, Item}, where Item is the rear item of Q, or empty -if Q is empty.

    Example 1:

    1> queue:peek_r(queue:new()).
    +if Q is empty.

    Example 1:

    1> queue:peek_r(queue:new()).
     empty
    -2> Queue = queue:from_list([1,2,3,4,5]).
    -{[5,4,3],[1,2]}
    -3> queue:peek_r(Queue).
    -{value, 5}
    +2>
    Queue = queue:from_list([1,2,3,4,5]). +{[5,4,3],[1,2]} +3> queue:peek_r(Queue). +{value, 5}
    @@ -893,10 +893,10 @@ -

    Inserts Item at the head of queue Q1. Returns the new queue Q2.

    Example:

    1> Queue = queue:cons(0, queue:from_list([1,2,3])).
    -{[3,2],[0,1]}
    -2> queue:to_list(Queue).
    -[0,1,2,3]
    +

    Inserts Item at the head of queue Q1. Returns the new queue Q2.

    Example:

    1> Queue = queue:cons(0, queue:from_list([1,2,3])).
    +{[3,2],[0,1]}
    +2> queue:to_list(Queue).
    +[0,1,2,3]
    @@ -924,7 +924,7 @@ -

    Returns the tail item of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> queue:daeh(queue:from_list([1,2,3])).
    +

    Returns the tail item of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> queue:daeh(queue:from_list([1,2,3])).
     3
    @@ -953,7 +953,7 @@ -

    Returns Item from the head of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> queue:head(queue:from_list([1,2,3])).
    +

    Returns Item from the head of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> queue:head(queue:from_list([1,2,3])).
     1
    @@ -982,10 +982,10 @@ -

    Returns a queue Q2 that is the result of removing the tail item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:init(queue:from_list([1,2,3])).
    -{[2],[1]}
    -2> queue:to_list(Queue).
    -[1,2]
    +

    Returns a queue Q2 that is the result of removing the tail item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:init(queue:from_list([1,2,3])).
    +{[2],[1]}
    +2> queue:to_list(Queue).
    +[1,2]
    @@ -1045,7 +1045,7 @@ -

    Returns the tail item of queue Q.

    Fails with reason empty if Q is empty.

    Example:

    1> queue:last(queue:from_list([1,2,3])).
    +

    Returns the tail item of queue Q.

    Fails with reason empty if Q is empty.

    Example:

    1> queue:last(queue:from_list([1,2,3])).
     3
    @@ -1074,10 +1074,10 @@ -

    Returns a queue Q2 that is the result of removing the tail item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:liat(queue:from_list([1,2,3])).
    -{[2],[1]}
    -2> queue:to_list(Queue).
    -[1,2]
    +

    Returns a queue Q2 that is the result of removing the tail item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:liat(queue:from_list([1,2,3])).
    +{[2],[1]}
    +2> queue:to_list(Queue).
    +[1,2]
    @@ -1105,10 +1105,10 @@ -

    Inserts Item as the tail item of queue Q1. Returns the new queue Q2.

    Example:

    1> Queue = queue:snoc(queue:from_list([1,2,3]), 4).
    -{[4,3,2],[1]}
    -2> queue:to_list(Queue).
    -[1,2,3,4]
    +

    Inserts Item as the tail item of queue Q1. Returns the new queue Q2.

    Example:

    1> Queue = queue:snoc(queue:from_list([1,2,3]), 4).
    +{[4,3,2],[1]}
    +2> queue:to_list(Queue).
    +[1,2,3,4]
    @@ -1179,10 +1179,10 @@

    Returns true if Pred(Item) returns true for all items Item in Q, -otherwise false.

    Example:

    1> Queue = queue:from_list([1,2,3,4,5]).
    -2> queue:all(fun (E) -> E > 3 end, Queue).
    +otherwise false.

    Example:

    1> Queue = queue:from_list([1,2,3,4,5]).
    +2> queue:all(fun (E) -> E > 3 end, Queue).
     false
    -3> queue:all(fun (E) -> E > 0 end, Queue).
    +3> queue:all(fun (E) -> E > 0 end, Queue).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/rand.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2577))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/rand.html	2026-08-21 04:00:30.069364062 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/rand.html	2026-08-21 04:00:30.069364062 +0000
    @@ -154,40 +154,40 @@
     %% If there is no state there, [`seed(default)`](`seed/1`)
     %% is implicitly called first:
     %%
    -1> R0 = rand:uniform(),
    -   is_float(R0) andalso 0.0 =< R0 andalso R0 < 1.0.
    +1> R0 = rand:uniform(),
    +   is_float(R0) andalso 0.0 =< R0 andalso R0 < 1.0.
     true
    -2> R1 = rand:uniform(),
    -   is_float(R1) andalso 0.0 =< R1 andalso R1 < 1.0.
    +2> R1 = rand:uniform(),
    +   is_float(R1) andalso 0.0 =< R1 andalso R1 < 1.0.
     true
     
     %% Generate a uniformly distributed integer in the range 1..4711:
     %%
    -3> K0 = rand:uniform(4711),
    -   is_integer(K0) andalso 1 =< K0 andalso K0 =< 4711.
    +3> K0 = rand:uniform(4711),
    +   is_integer(K0) andalso 1 =< K0 andalso K0 =< 4711.
     true
     
     %% Generate a binary with 16 bytes, uniformly distributed:
     %%
    -4> B0 = rand:bytes(16),
    -   byte_size(B0) == 16.
    +4> B0 = rand:bytes(16),
    +   byte_size(B0) == 16.
     true
     
     %% Select and initialize a specified algorithm,
     %% with an automatic default seed, then generate
     %% a floating point number:
     %%
    -5> rand:seed(exro928ss).
    -6> R2 = rand:uniform(),
    -   is_float(R2) andalso 0.0 =< R2 andalso R2 < 1.0.
    +5> rand:seed(exro928ss).
    +6> R2 = rand:uniform(),
    +   is_float(R2) andalso 0.0 =< R2 andalso R2 < 1.0.
     true
     
     %% Select and initialize a specified algorithm
     %% with a specified seed, then generate
     %% a floating point number:
     %%
    -7> rand:seed(exro928ss, 123456789).
    -8> R3 = rand:uniform().
    +7> rand:seed(exro928ss, 123456789).
    +8> R3 = rand:uniform().
     0.48303622772415256
     
     %% Select and initialize a specific algorithm,
    @@ -195,28 +195,28 @@
     %% with explicit generator state, then generate
     %% two floating point numbers.
     %%
    -9>  S0 = rand:seed_s(exsss).
    -10> {R4, S1} = rand:uniform_s(S0),
    -    is_float(R4) andalso 0.0 =< R4 andalso R4 < 1.0.
    +9>  S0 = rand:seed_s(exsss).
    +10> {R4, S1} = rand:uniform_s(S0),
    +    is_float(R4) andalso 0.0 =< R4 andalso R4 < 1.0.
     true
    -11> {R5, S2} = rand:uniform_s(S1),
    -    is_float(R5) andalso 0.0 =< R5 andalso R5 < 1.0.
    +11> {R5, S2} = rand:uniform_s(S1),
    +    is_float(R5) andalso 0.0 =< R5 andalso R5 < 1.0.
     true
     %% Repeat the first after seed
    -12> {R4, _} = rand:uniform_s(S0).
    +12> {R4, _} = rand:uniform_s(S0).
     
     %% Generate a standard normal distribution number
     %% using the built-in fast Ziggurat Method:
     %%
    -13> {SND0, S3} = rand:normal_s(S2),
    -    is_float(SND0).
    +13> {SND0, S3} = rand:normal_s(S2),
    +    is_float(SND0).
     true
     
     %% Generate a normal distribution number
     %% with mean -3 and variance 0.5:
     %%
    -14> {ND0, S4} = rand:normal_s(-3, 0.5, S3),
    -    is_float(ND0).
    +14> {ND0, S4} = rand:normal_s(-3, 0.5, S3),
    +    is_float(ND0).
     true
     
     %% Generate a textbook basic form Box-Muller
    @@ -224,14 +224,14 @@
     %% distribution as the built-in Ziggurat method above,
     %% but is much slower:
     %%
    -15> R6 = rand:uniform_real(),
    -    is_float(R6) andalso 0.0 < R6 andalso R6 < 1.0.
    +15> R6 = rand:uniform_real(),
    +    is_float(R6) andalso 0.0 < R6 andalso R6 < 1.0.
     true
    -16> R7 = rand:uniform(),
    -    is_float(R7) andalso 0.0 =< R7 andalso R7 < 1.0.
    +16> R7 = rand:uniform(),
    +    is_float(R7) andalso 0.0 =< R7 andalso R7 < 1.0.
     true
     %% R6 cannot be equal to 0.0 so math:log/1 will never fail
    -17> SND1 = math:sqrt(-2 * math:log(R6)) * math:cos(math:pi() * R7).

    Algorithms

    The base generator algorithms implement the +17> SND1 = math:sqrt(-2 * math:log(R6)) * math:cos(math:pi() * R7).

    Algorithms

    The base generator algorithms implement the Xoroshiro and Xorshift algorithms by Sebastiano Vigna. During an iteration they generate an integer (at least 58-bit) and operate on a state of several integers. @@ -298,7 +298,7 @@ up to (and included) 16TB, with the exception of binary rank tests, which fail due to the lowest bit being an LFSR; all other bits pass all tests. We suggest to use a sign test to extract a random Boolean value.

    If this is a problem; to generate a boolean with these algorithms, -use something like this:

    (rand:uniform(256) > 128) % -> boolean()
    ((rand:uniform(256) - 1) bsr 7) % -> 0 | 1

    For a general range, with N = 1 for exrop, and N = 3 for exs1024s:

    (((rand:uniform(Range bsl N) - 1) bsr N) + 1)

    The floating point generating functions in this module waste the lowest bits +use something like this:

    (rand:uniform(256) > 128) % -> boolean()
    ((rand:uniform(256) - 1) bsr 7) % -> 0 | 1

    For a general range, with N = 1 for exrop, and N = 3 for exs1024s:

    (((rand:uniform(Range bsl N) - 1) bsr N) + 1)

    The floating point generating functions in this module waste the lowest bits when converting from an integer so they avoid this snag.

    Niche algorithms

    The niche algorithms API contains special purpose algorithms that do not use the plug-in framework, mainly for performance reasons.

    Since these algorithms lack the plug-in framework support, generating numbers @@ -1508,7 +1508,7 @@ 16#7fa6502 * 2^32 - 1, which have been selected, in collaboration with Sebastiano Vigna, to avoid bignum operations and still get good statistical quality. It has been named "MWC59" and can be written as:

    C = CX0 bsr 32
    -X = CX0 band ((1 bsl 32)-1))
    +X = CX0 band ((1 bsl 32)-1))
     CX1 = 16#7fa6502 * X + C

    Because the generator uses a multiplier that is a power of 2 it gets statistical flaws for collision tests and birthday spacings tests in 2 and 3 dimensions, and these caveats apply even when looking @@ -2416,10 +2416,10 @@ equally spaced in the interval.

    Warning

    This function may return exactly 0.0 which can be fatal for certain applications. If that is undesired you can use (1.0 - rand:uniform()) to get the interval 0.0 < X =< 1.0, or instead use uniform_real/0.

    If neither endpoint is desired you can achieve the range -0.0 < X < 1.0 using test and re-try like this:

    my_uniform() ->
    -    case rand:uniform() of
    +0.0 < X < 1.0 using test and re-try like this:

    my_uniform() ->
    +    case rand:uniform() of
             X when 0.0 < X -> X;
    -        _ -> my_uniform()
    +        _ -> my_uniform()
         end.
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/random.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (756)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/random.html 2026-08-21 04:00:30.090364199 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/random.html 2026-08-21 04:00:30.091364205 +0000 @@ -431,9 +431,9 @@

    Seeds random number generation with integer values in the process dictionary and -returns the old state.

    The following is an easy way of obtaining a unique value to seed with:

    random:seed(erlang:phash2([node()]),
    -            erlang:monotonic_time(),
    -            erlang:unique_integer())

    For details, see erlang:phash2/1, erlang:node/0, erlang:monotonic_time/0, +returns the old state.

    The following is an easy way of obtaining a unique value to seed with:

    random:seed(erlang:phash2([node()]),
    +            erlang:monotonic_time(),
    +            erlang:unique_integer())

    For details, see erlang:phash2/1, erlang:node/0, erlang:monotonic_time/0, and erlang:unique_integer/0.

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/re.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2349)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/re.html 2026-08-21 04:00:30.143364544 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/re.html 2026-08-21 04:00:30.143364544 +0000 @@ -2490,32 +2490,32 @@

    Takes a compiled regular expression and an item, and returns the relevant data from the regular expression.

    The only supported item is namelist, which returns the tuple {namelist, [binary()]}, -containing the names of all (unique) named subpatterns in the regular expression.

    For example:

    1> {ok,MP} = re:compile("(?<A>A)|(?<B>B)|(?<C>C)").
    -{ok,{re_pattern,3,0,0,
    -                <<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,
    -                  255,255,...>>}}
    -2> re:inspect(MP,namelist).
    -{namelist,[<<"A">>,<<"B">>,<<"C">>]}
    -3> {ok,MPD} = re:compile("(?<C>A)|(?<B>B)|(?<C>C)",[dupnames]).
    -{ok,{re_pattern,3,0,0,
    -                <<69,82,67,80,119,0,0,0,0,0,8,0,1,0,0,0,255,255,255,255,
    -                  255,255,...>>}}
    -4> re:inspect(MPD,namelist).
    -{namelist,[<<"B">>,<<"C">>]}

    Notice in the second example that the duplicate name only occurs once in the +containing the names of all (unique) named subpatterns in the regular expression.

    For example:

    1> {ok,MP} = re:compile("(?<A>A)|(?<B>B)|(?<C>C)").
    +{ok,{re_pattern,3,0,0,
    +                <<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,
    +                  255,255,...>>}}
    +2> re:inspect(MP,namelist).
    +{namelist,[<<"A">>,<<"B">>,<<"C">>]}
    +3> {ok,MPD} = re:compile("(?<C>A)|(?<B>B)|(?<C>C)",[dupnames]).
    +{ok,{re_pattern,3,0,0,
    +                <<69,82,67,80,119,0,0,0,0,0,8,0,1,0,0,0,255,255,255,255,
    +                  255,255,...>>}}
    +4> re:inspect(MPD,namelist).
    +{namelist,[<<"B">>,<<"C">>]}

    Notice in the second example that the duplicate name only occurs once in the returned list, and that the list is in alphabetical order regardless of where the names are positioned in the regular expression. The order of the names is the same as the order of captured subexpressions if {capture, all_names} is specified as an option to run/3. You can therefore create a name-to-value -mapping from the result of run/3 like this:

    1> {ok,MP} = re:compile("(?<A>A)|(?<B>B)|(?<C>C)").
    -{ok,{re_pattern,3,0,0,
    -                <<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,
    -                  255,255,...>>}}
    -2> {namelist, N} = re:inspect(MP,namelist).
    -{namelist,[<<"A">>,<<"B">>,<<"C">>]}
    -3> {match,L} = re:run("AA",MP,[{capture,all_names,binary}]).
    -{match,[<<"A">>,<<>>,<<>>]}
    -4> NameMap = lists:zip(N,L).
    -[{<<"A">>,<<"A">>},{<<"B">>,<<>>},{<<"C">>,<<>>}]
    +mapping from the result of run/3 like this:

    1> {ok,MP} = re:compile("(?<A>A)|(?<B>B)|(?<C>C)").
    +{ok,{re_pattern,3,0,0,
    +                <<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,
    +                  255,255,...>>}}
    +2> {namelist, N} = re:inspect(MP,namelist).
    +{namelist,[<<"A">>,<<"B">>,<<"C">>]}
    +3> {match,L} = re:run("AA",MP,[{capture,all_names,binary}]).
    +{match,[<<"A">>,<<>>,<<>>]}
    +4> NameMap = lists:zip(N,L).
    +[{<<"A">>,<<"A">>},{<<"B">>,<<>>},{<<"C">>,<<>>}]
    @@ -2604,16 +2604,16 @@ subexpression number N, is inserted in the result. If no subexpression with that number is generated by the regular expression, nothing is inserted.

    To insert an & or a \ in the result, precede it with a \. Notice that Erlang already gives a special meaning to \ in literal strings, so a single \ must be -written as "\\" and therefore a double \ as "\\\\".

    Example:

    1> re:replace("abcd","c","[&]",[{return,list}]).
    -"ab[c]d"

    while

    2> re:replace("abcd","c","[\\&]",[{return,list}]).
    +written as "\\" and therefore a double \ as "\\\\".

    Example:

    1> re:replace("abcd","c","[&]",[{return,list}]).
    +"ab[c]d"

    while

    2> re:replace("abcd","c","[\\&]",[{return,list}]).
     "ab[&]d"

    If the replacement is given as a fun, it will be called with the whole matching expression as the first argument and a list of subexpression matches in the order in which they appear in the regular expression. The returned value will be -inserted in the result.

    Example:

    3> re:replace("abcd", ".(.)",
    -    fun(Whole, [<<C>>]) ->
    -         <<$#, Whole/binary, $-, (C - $a + $A), $#>>
    +inserted in the result.

    Example:

    3> re:replace("abcd", ".(.)",
    +    fun(Whole, [<<C>>]) ->
    +         <<$#, Whole/binary, $-, (C - $a + $A), $#>>
         end,
    -    [{return, list}]).
    +    [{return, list}]).
     "#ab-B#cd"

    Note

    Non-matching optional subexpressions will not be included in the list of subexpression matches if they are the last subexpressions in the regular expression.

    Example:

    The regular expression "(a)(b)?(c)?" ("a", optionally followed by "b", @@ -2734,7 +2734,7 @@ run/3 handles empty matches in the same way as Perl: a zero-length match at any point is also retried with options [anchored, notempty_atstart]. If that search gives a result of length > 0, -the result is included. Example:

    re:run("cat","(|at)",[global]).

    The following matchings are performed:

    • At offset 0 - The regular expression (|at) first match at the +the result is included. Example:

      re:run("cat","(|at)",[global]).

      The following matchings are performed:

      • At offset 0 - The regular expression (|at) first match at the initial position of string cat, giving the result set [{0,0},{0,0}] (the second {0,0} is because of the subexpression marked by the parentheses). As the length of the match is 0, we do not advance to the next position yet.

      • At offset 0 with [anchored, notempty_atstart] - The search is @@ -2746,7 +2746,7 @@ of results and the position in the search string is advanced two steps.

      • At offset 3 - The search once again matches the empty string, giving [{3,0},{3,0}].

      • At offset 1 with [anchored, notempty_atstart] - This gives no result of length > 0 and we are at the last position, so the global search is -complete.

      The result of the call is:

      {match,[[{0,0},{0,0}],[{1,0},{1,0}],[{1,2},{1,2}],[{3,0},{3,0}]]}
    • notempty - An empty string is not considered to be a valid match if this +complete.

    The result of the call is:

    {match,[[{0,0},{0,0}],[{1,0},{1,0}],[{1,2},{1,2}],[{3,0},{3,0}]]}
  • notempty - An empty string is not considered to be a valid match if this option is specified. If alternatives in the pattern exist, they are tried. If all the alternatives match the empty string, the entire match fails.

    Example:

    If the following pattern is applied to a string not beginning with "a" or "b", it would normally match the empty string at the start of the subject:

    a?b?

    With option notempty, this match is invalid, so run/3 searches @@ -2817,12 +2817,12 @@ instead of the stack, the amount of heap memory that can be used.

    The Erlang VM uses a PCRE library where heap memory is used when regular expression match recursion occurs. This therefore limits the use of machine heap, not C stack.

    Specifying a lower value can result in matches with deep recursion failing, -when they should have matched:

    1> re:run("aaaaaaaaaaaaaz","(a+)*z").
    -{match,[{0,14},{0,13}]}
    -2> re:run("aaaaaaaaaaaaaz","(a+)*z",[{match_limit_recursion,5}]).
    +when they should have matched:

    1> re:run("aaaaaaaaaaaaaz","(a+)*z").
    +{match,[{0,14},{0,13}]}
    +2> re:run("aaaaaaaaaaaaaz","(a+)*z",[{match_limit_recursion,5}]).
     nomatch
    -3> re:run("aaaaaaaaaaaaaz","(a+)*z",[{match_limit_recursion,5},report_errors]).
    -{error,match_limit_recursion}

    This option and option match_limit are only to be used in rare cases. +3> re:run("aaaaaaaaaaaaaz","(a+)*z",[{match_limit_recursion,5},report_errors]). +{error,match_limit_recursion}

    This option and option match_limit are only to be used in rare cases. Understanding of the PCRE library internals is recommended before tampering with these limits.

  • {offset, integer() >= 0} - Start matching at the offset (position) specified in the subject string. The offset is zero-based, so that the default @@ -2835,9 +2835,9 @@ capturing).

    As an example of the default behavior, the following call returns, as first and only captured string, the matching part of the subject ("abcd" in the middle) as an index pair {3,4}, where character positions are zero-based, -just as in offsets:

    re:run("ABCabcdABC","abcd",[]).

    The return value of this call is:

    {match,[{3,4}]}

    Another (and quite common) case is where the regular expression matches all of -the subject:

    re:run("ABCabcdABC",".*abcd.*",[]).

    Here the return value correspondingly points out all of the string, beginning -at index 0, and it is 10 characters long:

    {match,[{0,10}]}

    If the regular expression contains capturing subpatterns, like in:

    re:run("ABCabcdABC",".*(abcd).*",[]).

    all of the matched subject is captured, as well as the captured substrings:

    {match,[{0,10},{3,4}]}

    The complete matching pattern always gives the first return value in the list +just as in offsets:

    re:run("ABCabcdABC","abcd",[]).

    The return value of this call is:

    {match,[{3,4}]}

    Another (and quite common) case is where the regular expression matches all of +the subject:

    re:run("ABCabcdABC",".*abcd.*",[]).

    Here the return value correspondingly points out all of the string, beginning +at index 0, and it is 10 characters long:

    {match,[{0,10}]}

    If the regular expression contains capturing subpatterns, like in:

    re:run("ABCabcdABC",".*(abcd).*",[]).

    all of the matched subject is captured, as well as the captured substrings:

    {match,[{0,10},{3,4}]}

    The complete matching pattern always gives the first return value in the list and the remaining subpatterns are added in the order they occurred in the regular expression.

    The capture tuple is built up as follows:

    • ValueSpec - Specifies which captured (sub)patterns are to be returned. ValueSpec can either be an atom describing a predefined set of return @@ -2862,12 +2862,12 @@ subpatterns (see below) in the regular expression, one can use atom/0s or string/0s to specify the subpatterns to be returned. For example, consider the regular expression:

      ".*(abcd).*"

      matched against string "ABCabcdABC", capturing only the "abcd" part (the -first explicit subpattern):

      re:run("ABCabcdABC",".*(abcd).*",[{capture,[1]}]).

      The call gives the following result, as the first explicitly captured +first explicit subpattern):

      re:run("ABCabcdABC",".*(abcd).*",[{capture,[1]}]).

      The call gives the following result, as the first explicitly captured subpattern is "(abcd)", matching "abcd" in the subject, at (zero-based) -position 3, of length 4:

      {match,[{3,4}]}

      Consider the same regular expression, but with the subpattern explicitly +position 3, of length 4:

      {match,[{3,4}]}

      Consider the same regular expression, but with the subpattern explicitly named 'FOO':

      ".*(?<FOO>abcd).*"

      With this expression, we could still give the index of the subpattern with -the following call:

      re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,[1]}]).

      giving the same result as before. But, as the subpattern is named, we can -also specify its name in the value list:

      re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,['FOO']}]).

      This would give the same result as the earlier examples, namely:

      {match,[{3,4}]}

      The values list can specify indexes or names not present in the regular +the following call:

      re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,[1]}]).

      giving the same result as before. But, as the subpattern is named, we can +also specify its name in the value list:

      re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,['FOO']}]).

      This would give the same result as the earlier examples, namely:

      {match,[{3,4}]}

      The values list can specify indexes or names not present in the regular expression, in which case the return values vary depending on the type. If the type is index, the tuple {-1,0} is returned for values with no corresponding subpattern in the regular expression, but for the other types @@ -2902,12 +2902,12 @@ string:

      "ABCabcdABC"

      the subpattern at index 2 does not match, as "abdd" is not present in the string, but the complete pattern matches (because of the alternative a(..d)). The subpattern at index 2 is therefore unassigned and the default -return value is:

      {match,[{0,10},{3,4},{-1,0},{4,3}]}

      Setting the capture Type to binary gives:

      {match,[<<"ABCabcdABC">>,<<"abcd">>,<<>>,<<"bcd">>]}

      Here the empty binary (<<>>) represents the unassigned subpattern. In the +return value is:

      {match,[{0,10},{3,4},{-1,0},{4,3}]}

      Setting the capture Type to binary gives:

      {match,[<<"ABCabcdABC">>,<<"abcd">>,<<>>,<<"bcd">>]}

      Here the empty binary (<<>>) represents the unassigned subpattern. In the binary case, some information about the matching is therefore lost, as <<>> can also be an empty string captured.

      If differentiation between empty matches and non-existing subpatterns is necessary, use the type index and do the conversion to the final type in Erlang code.

      When option global is speciified, the capture specification affects each -match separately, so that:

      re:run("cacb","c(a|b)",[global,{capture,[1],list}]).

      gives

      {match,[["a"],["b"]]}

    For a descriptions of options only affecting the compilation step, see +match separately, so that:

    re:run("cacb","c(a|b)",[global,{capture,[1],list}]).

    gives

    {match,[["a"],["b"]]}
  • For a descriptions of options only affecting the compilation step, see compile/2.

    @@ -2994,7 +2994,7 @@ compilation option is specified to this function, both the regular expression and Subject are to be specified as valid Unicode charlist()s.

    The result is given as a list of "strings", the preferred data type specified in option return (default iodata).

    If subexpressions are specified in the regular expression, the matching -subexpressions are returned in the resulting list as well. For example:

    re:split("Erlang","[ln]",[{return,list}]).

    gives

    ["Er","a","g"]

    while

    re:split("Erlang","([ln])",[{return,list}]).

    gives

    ["Er","l","a","n","g"]

    The text matching the subexpression (marked by the parentheses in the regular +subexpressions are returned in the resulting list as well. For example:

    re:split("Erlang","[ln]",[{return,list}]).

    gives

    ["Er","a","g"]

    while

    re:split("Erlang","([ln])",[{return,list}]).

    gives

    ["Er","l","a","n","g"]

    The text matching the subexpression (marked by the parentheses in the regular expression) is inserted in the result list where it was found. This means that concatenating the result of a split where the whole regular expression is a single subexpression (as in the last example) always results in the original @@ -3002,21 +3002,21 @@ "g"), nothing is inserted after that. To make the group of strings and the parts matching the subexpressions more obvious, one can use option group, which groups together the part of the subject string with the parts matching the -subexpressions when the string was split:

    re:split("Erlang","([ln])",[{return,list},group]).

    gives

    [["Er","l"],["a","n"],["g"]]

    Here the regular expression first matched the "l", causing "Er" to be the first +subexpressions when the string was split:

    re:split("Erlang","([ln])",[{return,list},group]).

    gives

    [["Er","l"],["a","n"],["g"]]

    Here the regular expression first matched the "l", causing "Er" to be the first part in the result. When the regular expression matched, the (only) subexpression was bound to the "l", so the "l" is inserted in the group together with "Er". The next match is of the "n", making "a" the next part to be returned. As the subexpression is bound to substring "n" in this case, the "n" is inserted into this group. The last group consists of the remaining string, as no more matches are found.

    By default, all parts of the string, including the empty strings, are returned -from the function, for example:

    re:split("Erlang","[lg]",[{return,list}]).

    gives

    ["Er","an",[]]

    as the matching of the "g" in the end of the string leaves an empty rest, which +from the function, for example:

    re:split("Erlang","[lg]",[{return,list}]).

    gives

    ["Er","an",[]]

    as the matching of the "g" in the end of the string leaves an empty rest, which is also returned. This behavior differs from the default behavior of the split function in Perl, where empty strings at the end are by default removed. To get -the "trimming" default behavior of Perl, specify trim as an option:

    re:split("Erlang","[lg]",[{return,list},trim]).

    gives

    ["Er","an"]

    The "trim" option says; "give me as many parts as possible except the empty +the "trimming" default behavior of Perl, specify trim as an option:

    re:split("Erlang","[lg]",[{return,list},trim]).

    gives

    ["Er","an"]

    The "trim" option says; "give me as many parts as possible except the empty ones", which sometimes can be useful. You can also specify how many parts you -want, by specifying {parts,N}:

    re:split("Erlang","[lg]",[{return,list},{parts,2}]).

    gives

    ["Er","ang"]

    Notice that the last part is "ang", not "an", as splitting was specified into +want, by specifying {parts,N}:

    re:split("Erlang","[lg]",[{return,list},{parts,2}]).

    gives

    ["Er","ang"]

    Notice that the last part is "ang", not "an", as splitting was specified into two parts, and the splitting stops when enough parts are given, which is why the -result differs from that of trim.

    More than three parts are not possible with this indata, so

    re:split("Erlang","[lg]",[{return,list},{parts,4}]).

    gives the same result as the default, which is to be viewed as "an infinite +result differs from that of trim.

    More than three parts are not possible with this indata, so

    re:split("Erlang","[lg]",[{return,list},{parts,4}]).

    gives the same result as the default, which is to be viewed as "an infinite number of parts".

    Specifying 0 as the number of parts gives the same effect as option trim. If subexpressions are captured, empty subexpressions matched at the end are also stripped from the result if trim or {parts,0} is specified.

    The trim behavior corresponds exactly to the Perl default. {parts,N}, where /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/sets.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1668)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/sets.html 2026-08-21 04:00:30.179364778 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/sets.html 2026-08-21 04:00:30.179364778 +0000 @@ -114,11 +114,11 @@ respect to the aforementioned functions, their overall behavior may differ. As mentioned, this module considers elements as different if and only if they do not match (=:=), while both ordsets and gb_sets consider elements -as different if and only if they do not compare equal (==).

    Examples

    1> sets:is_element(1.0, sets:from_list([1])).
    +as different if and only if they do not compare equal (==).

    Examples

    1> sets:is_element(1.0, sets:from_list([1])).
     false
    -2> ordsets:is_element(1.0, ordsets:from_list([1])).
    +2> ordsets:is_element(1.0, ordsets:from_list([1])).
     true
    -3> gb_sets:is_element(1.0, gb_sets:from_list([1])).
    +3> gb_sets:is_element(1.0, gb_sets:from_list([1])).
     true

    See Also

    gb_sets, ordsets

    @@ -503,16 +503,16 @@ -

    Returns a new set formed from Set1 with Element inserted.

    Examples

    1> S0 = sets:new().
    -2> S1 = sets:add_element(7, S0).
    -3> sets:to_list(S1).
    -[7]
    -4> S2 = sets:add_element(42, S1).
    -5> lists:sort(sets:to_list(S2)).
    -[7,42]
    -6> S2 = sets:add_element(42, S1).
    -7> lists:sort(sets:to_list(S2)).
    -[7,42]
    +

    Returns a new set formed from Set1 with Element inserted.

    Examples

    1> S0 = sets:new().
    +2> S1 = sets:add_element(7, S0).
    +3> sets:to_list(S1).
    +[7]
    +4> S2 = sets:add_element(42, S1).
    +5> lists:sort(sets:to_list(S2)).
    +[7,42]
    +6> S2 = sets:add_element(42, S1).
    +7> lists:sort(sets:to_list(S2)).
    +[7,42]
    @@ -540,12 +540,12 @@ -

    Returns a copy of Set1 with Element removed.

    Examples

    1> S = sets:from_list([a,b]).
    -2> sets:to_list(sets:del_element(b, S)).
    -[a]
    -3> S = sets:del_element(x, S).
    -4> lists:sort(sets:to_list(S)).
    -[a,b]
    +

    Returns a copy of Set1 with Element removed.

    Examples

    1> S = sets:from_list([a,b]).
    +2> sets:to_list(sets:del_element(b, S)).
    +[a]
    +3> S = sets:del_element(x, S).
    +4> lists:sort(sets:to_list(S)).
    +[a,b]
    @@ -574,11 +574,11 @@ -

    Filters elements in Set1 using predicate function Pred.

    Examples

    1> S = sets:from_list([1,2,3,4,5,6,7]).
    -2> IsEven = fun(N) -> N rem 2 =:= 0 end.
    -3> Filtered = sets:filter(IsEven, S).
    -4> lists:sort(sets:to_list(Filtered)).
    -[2,4,6]
    +

    Filters elements in Set1 using predicate function Pred.

    Examples

    1> S = sets:from_list([1,2,3,4,5,6,7]).
    +2> IsEven = fun(N) -> N rem 2 =:= 0 end.
    +3> Filtered = sets:filter(IsEven, S).
    +4> lists:sort(sets:to_list(Filtered)).
    +[2,4,6]
    @@ -615,17 +615,17 @@

    Calls Fun(Elem) for each Elem of Set1 to update or remove elements from Set1.

    Fun/1 must return either a Boolean or a tuple {true, Value}. The function returns the set of elements for which Fun returns a new -value, with true being equivalent to {true, Elem}.

    sets:filtermap/2 behaves as if it were defined as follows:

    filtermap(Fun, Set1) ->
    -    sets:from_list(lists:filtermap(Fun, Set1)).

    Examples

    1> S = sets:from_list([2,4,5,6,8,9])
    -2> F = fun(X) ->
    +value, with true being equivalent to {true, Elem}.

    sets:filtermap/2 behaves as if it were defined as follows:

    filtermap(Fun, Set1) ->
    +    sets:from_list(lists:filtermap(Fun, Set1)).

    Examples

    1> S = sets:from_list([2,4,5,6,8,9])
    +2> F = fun(X) ->
                case X rem 2 of
    -               0 -> {true, X div 2};
    +               0 -> {true, X div 2};
                    1 -> false
                end
             end.
    -3> Set = sets:filtermap(F, S).
    -4> lists:sort(sets:to_list(Set)).
    -[1,2,3,4]
    +3>
    Set = sets:filtermap(F, S). +4> lists:sort(sets:to_list(Set)). +[1,2,3,4]
    @@ -661,9 +661,9 @@

    Folds Function over every element in Set and returns the final value of -the accumulator.

    The evaluation order is undefined.

    Examples

    1> S = sets:from_list([1,2,3,4]).
    +the accumulator.

    The evaluation order is undefined.

    Examples

    1> S = sets:from_list([1,2,3,4]).
     2> Plus = fun erlang:'+'/2.
    -3> sets:fold(Plus, 0, S).
    +3> sets:fold(Plus, 0, S).
     10
    @@ -692,9 +692,9 @@ -

    Returns a set of the elements in List.

    Examples

    1> S = sets:from_list([a,b,c]).
    -2> lists:sort(sets:to_list(S)).
    -[a,b,c]
    +

    Returns a set of the elements in List.

    Examples

    1> S = sets:from_list([a,b,c]).
    +2> lists:sort(sets:to_list(S)).
    +[a,b,c]
    @@ -724,9 +724,9 @@ -

    Returns a set of the elements in List of the given version.

    Examples

    1> S = sets:from_list([a,b,c], [{version, 1}]).
    -2> lists:sort(sets:to_list(S)).
    -[a,b,c]
    +

    Returns a set of the elements in List of the given version.

    Examples

    1> S = sets:from_list([a,b,c], [{version, 1}]).
    +2> lists:sort(sets:to_list(S)).
    +[a,b,c]
    @@ -755,15 +755,15 @@

    Returns the intersection of the non-empty list of sets.

    The intersection of multiple sets is a new set that contains only the -elements that are present in all sets.

    Examples

    1> S0 = sets:from_list([a,b,c,d]).
    -2> S1 = sets:from_list([d,e,f]).
    -3> S2 = sets:from_list([q,r])
    -4> Sets = [S0, S1, S2].
    -5> sets:to_list(sets:intersection([S0, S1, S2])).
    -[]
    -6> sets:to_list(sets:intersection([S0, S1])).
    -[d]
    -7> sets:intersection([]).
    +elements that are present in all sets.

    Examples

    1> S0 = sets:from_list([a,b,c,d]).
    +2> S1 = sets:from_list([d,e,f]).
    +3> S2 = sets:from_list([q,r])
    +4> Sets = [S0, S1, S2].
    +5> sets:to_list(sets:intersection([S0, S1, S2])).
    +[]
    +6> sets:to_list(sets:intersection([S0, S1])).
    +[d]
    +7> sets:intersection([]).
     ** exception error: no function clause matching sets:intersection([])
    @@ -794,14 +794,14 @@

    Returns the intersection of Set1 and Set2.

    The intersection of two sets is a new set that contains only the -elements that are present in both sets.

    Examples

    1> S0 = sets:from_list([a,b,c,d]).
    -2> S1 = sets:from_list([c,d,e,f]).
    -3> S2 = sets:from_list([q,r]).
    -4> Intersection = sets:intersection(S0, S1).
    -5> lists:sort(sets:to_list(Intersection)).
    -[c,d]
    -6> sets:to_list(sets:intersection(S1, S2)).
    -[]
    +elements that are present in both sets.

    Examples

    1> S0 = sets:from_list([a,b,c,d]).
    +2> S1 = sets:from_list([c,d,e,f]).
    +3> S2 = sets:from_list([q,r]).
    +4> Intersection = sets:intersection(S0, S1).
    +5> lists:sort(sets:to_list(Intersection)).
    +[c,d]
    +6> sets:to_list(sets:intersection(S1, S2)).
    +[]
    @@ -831,12 +831,12 @@

    Returns true if Set1 and Set2 are disjoint; otherwise, returns false.

    Two sets are disjoint if they have no elements in common.

    This function is equivalent to sets:intersection(Set1, Set2) =:= [], -but faster.

    Examples

    1> S0 = sets:from_list([a,b,c,d]).
    -2> S1 = sets:from_list([d,e,f]).
    -3> S2 = sets:from_list([q,r])
    -4> sets:is_disjoint(S0, S1).
    +but faster.

    Examples

    1> S0 = sets:from_list([a,b,c,d]).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/shell.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (917))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/shell.html	2026-08-21 04:00:30.209364973 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/shell.html	2026-08-21 04:00:30.209364973 +0000
    @@ -131,7 +131,7 @@
     definitions. To facilitate matters, record definitions in modules
     shell_default and user_default (if loaded) are read each time a new job is
     started. For example, adding the following line to user_default makes the
    -definition of file_info readily available in the shell:

    -include_lib("kernel/include/file.hrl").

    The shell runs in two modes:

    • Normal (possibly restricted) mode, in which commands can be edited and +definition of file_info readily available in the shell:

      -include_lib("kernel/include/file.hrl").

      The shell runs in two modes:

      • Normal (possibly restricted) mode, in which commands can be edited and expressions evaluated
      • Job Control Mode, JCL, in which jobs can be started, killed, detached, and connected

      Only the currently connected job can 'talk' to the shell.

      Shell Commands

      The commands below are the built-in shell commands that are always available. In most system the commands listed in the c module are also available in the @@ -187,30 +187,30 @@ records to a module file, where FilePath should include both the path to the file and the name of the module with .erl suffix.

      Example: src/my_module.erl

    Example

    The following example is a long dialog with the shell. Commands starting with > are inputs to the shell. All other lines are output from the shell.

    strider 1> erl
    -Erlang (BEAM) emulator version 5.3 [hipe] [threads:0]
    +Erlang (BEAM) emulator version 5.3 [hipe] [threads:0]
     
    -Eshell V5.3  (abort with ^G)
    +Eshell V5.3  (abort with ^G)
     1> Str = "abcd".
    -"abcd"

    Command 1 sets variable Str to string "abcd".

    2> L = length(Str).
    -4

    Command 2 sets L to the length of string Str.

    3> Descriptor = {L, list_to_atom(Str)}.
    -{4,abcd}

    Command 3 builds the tuple Descriptor, evaluating the BIF +"abcd"

    Command 1 sets variable Str to string "abcd".

    2> L = length(Str).
    +4

    Command 2 sets L to the length of string Str.

    3> Descriptor = {L, list_to_atom(Str)}.
    +{4,abcd}

    Command 3 builds the tuple Descriptor, evaluating the BIF list_to_atom/1 .

    4> L.
    -4

    Command 4 prints the value of variable L.

    5> b().
    -Descriptor = {4,abcd}
    +4

    Command 4 prints the value of variable L.

    5> b().
    +Descriptor = {4,abcd}
     L = 4
     Str = "abcd"
     ok

    Command 5 evaluates the internal shell command b(), which is an abbreviation of "bindings". This prints the current shell variables and their bindings. ok -at the end is the return value of function b().

    6> f(L).
    +at the end is the return value of function b().

    6> f(L).
     ok

    Command 6 evaluates the internal shell command f(L) (abbreviation of -"forget"). The value of variable L is removed.

    7> b().
    -Descriptor = {4,abcd}
    +"forget"). The value of variable L is removed.

    7> b().
    +Descriptor = {4,abcd}
     Str = "abcd"
    -ok

    Command 7 prints the new bindings.

    8> f(L).
    -ok

    Command 8 has no effect, as L has no value.

    9> {L, _} = Descriptor.
    -{4,abcd}

    Command 9 performs a pattern matching operation on Descriptor, binding a new +ok

    Command 7 prints the new bindings.

    8> f(L).
    +ok

    Command 8 has no effect, as L has no value.

    9> {L, _} = Descriptor.
    +{4,abcd}

    Command 9 performs a pattern matching operation on Descriptor, binding a new value to L.

    10> L.
    -4

    Command 10 prints the current value of L.

    11> {P, Q, R} = Descriptor.
    +4

    Command 10 prints the current value of L.

    11> {P, Q, R} = Descriptor.
     ** exception error: no match of right hand side value {4,abcd}

    Command 11 tries to match {P, Q, R} against Descriptor, which is {4, abc}. The match fails and none of the new variables become bound. The printout starting with "** exception error:" is not the value of the expression (the @@ -219,74 +219,74 @@ other variables (L, Str, and so on) are unchanged.

    12> P.
     * 1:1: variable 'P' is unbound
     13> Descriptor.
    -{4,abcd}

    Commands 12 and 13 show that P is unbound because the previous command failed, -and that Descriptor has not changed.

    14>{P, Q} = Descriptor.
    -{4,abcd}
    +{4,abcd}

    Commands 12 and 13 show that P is unbound because the previous command failed, +and that Descriptor has not changed.

    14>{P, Q} = Descriptor.
    +{4,abcd}
     15> P.
    -4

    Commands 14 and 15 show a correct match where P and Q are bound.

    16> f().
    -ok

    Command 16 clears all bindings.

    The next few commands assume that test1:demo(X) is defined as follows:

    demo(X) ->
    -    put(aa, worked),
    +4

    Commands 14 and 15 show a correct match where P and Q are bound.

    16> f().
    +ok

    Command 16 clears all bindings.

    The next few commands assume that test1:demo(X) is defined as follows:

    demo(X) ->
    +    put(aa, worked),
         X = 1,
    -    X + 10.
    17> put(aa, hello).
    +    X + 10.
    17> put(aa, hello).
     undefined
    -18> get(aa).
    +18> get(aa).
     hello

    Commands 17 and 18 set and inspect the value of item aa in the process -dictionary.

    19> Y = test1:demo(1).
    +dictionary.

    19> Y = test1:demo(1).
     11

    Command 19 evaluates test1:demo(1). The evaluation succeeds and the changes made in the process dictionary become visible to the shell. The new value of -dictionary item aa can be seen in command 20.

    20> get().
    -[{aa,worked}]
    -21> put(aa, hello).
    +dictionary item aa can be seen in command 20.

    20> get().
    +[{aa,worked}]
    +21> put(aa, hello).
     worked
    -22> Z = test1:demo(2).
    +22> Z = test1:demo(2).
     ** exception error: no match of right hand side value 1
          in function  test1:demo/1

    Commands 21 and 22 change the value of dictionary item aa to hello and call test1:demo(2). Evaluation fails and the changes made to the dictionary in test1:demo(2), before the error occurred, are discarded.

    23> Z.
     * 1:1: variable 'Z' is unbound
    -24> get(aa).
    +24> get(aa).
     hello

    Commands 23 and 24 show that Z was not bound and that dictionary item aa has -retained its original value.

    25> erase(), put(aa, hello).
    +retained its original value.

    25> erase(), put(aa, hello).
     undefined
    -26> spawn(test1, demo, [1]).
    +26> spawn(test1, demo, [1]).
     <0.57.0>
    -27> get(aa).
    +27> get(aa).
     hello

    Commands 25, 26, and 27 show the effect of evaluating test1:demo(1) in the background. In this case, the expression is evaluated in a newly spawned process. Any changes made in the process dictionary are local to the newly -spawned process and therefore not visible to the shell.

    28> io:format("hello hello\n").
    +spawned process and therefore not visible to the shell.

    28> io:format("hello hello\n").
     hello hello
     ok
    -29> e(28).
    +29> e(28).
     hello hello
     ok
    -30> v(28).
    +30> v(28).
     ok

    Commands 28, 29 and 30 use the history facilities of the shell. Command 29 re-evaluates command 28. Command 30 uses the value (result) of command 28. In the cases of a pure function (a function with no side effects), the result is the same. For a function with side effects, the result can be different.

    The next few commands show some record manipulation. It is assumed that ex.erl -defines a record as follows:

    -record(rec, {a, b = val()}).

    val() ->
        3.

    31> c(ex).
    -{ok,ex}
    -32> rr(ex).
    -[rec]

    Commands 31 and 32 compile file ex.erl and read the record definitions in +defines a record as follows:

    -record(rec, {a, b = val()}).

    val() ->
        3.

    31> c(ex).
    +{ok,ex}
    +32> rr(ex).
    +[rec]

    Commands 31 and 32 compile file ex.erl and read the record definitions in ex.beam. If the compiler did not output any record definitions on the BEAM -file, rr(ex) tries to read record definitions from the source file instead.

    33> rl(rec).
    --record(rec,{a,b = val()}).
    -ok

    Command 33 prints the definition of the record named rec.

    34> #rec{}.
    +file, rr(ex) tries to read record definitions from the source file instead.

    33> rl(rec).
    +-record(rec,{a,b = val()}).
    +ok

    Command 33 prints the definition of the record named rec.

    34> #rec{}.
     ** exception error: undefined shell command val/0

    Command 34 tries to create a rec record, but fails as function val/0 is -undefined.

    35> #rec{b = 3}.
    -#rec{a = undefined,b = 3}

    Command 35 shows the workaround: explicitly assign values to record fields that -cannot otherwise be initialized.

    36> rp(v(-1)).
    -#rec{a = undefined,b = 3}
    +undefined.

    35> #rec{b = 3}.
    +#rec{a = undefined,b = 3}

    Command 35 shows the workaround: explicitly assign values to record fields that +cannot otherwise be initialized.

    36> rp(v(-1)).
    +#rec{a = undefined,b = 3}
     ok

    Command 36 prints the newly created record using record definitions maintained -by the shell.

    37> rd(rec, {f = orddict:new()}).
    +by the shell.

    37> rd(rec, {f = orddict:new()}).
     rec

    Command 37 defines a record directly in the shell. The definition replaces the -one read from file ex.beam.

    38> #rec{}.
    -#rec{f = []}
    -ok

    Command 38 creates a record using the new definition, and prints the result.

    39> rd(rec, {c}), A.
    +one read from file ex.beam.

    38> #rec{}.
    +#rec{f = []}
    +ok

    Command 38 creates a record using the new definition, and prints the result.

    39> rd(rec, {c}), A.
     * 1:15: variable 'A' is unbound
    -40> #rec{}.
    -#rec{c = undefined}
    +40> #rec{}.
    +#rec{c = undefined}
     ok

    Command 39 and 40 show that record definitions are updated as side effects. The evaluation of the command fails, but the definition of rec has been carried out.

    For the next command, it is assumed that test1:loop(N) is defined as follows:

    loop(N) ->
        io:format("Hello Number: ~w~n", [N]),
        loop(N+1).

    41> test1:loop(0).
    @@ -312,31 +312,31 @@
     JCL mode the user can start and stop jobs.

    In this particular case, command i ("interrupt") terminates the looping program, and command c connects to the shell again. As the process was running in the background before we killed it, more printouts occur before message -"** exception exit: killed" is shown.

    42> E = ets:new(t, []).
    -#Ref<0.1662103692.2407923716.214192>

    Command 42 creates an ETS table.

    43> ets:insert({d,1,2}).
    +"** exception exit: killed" is shown.

    42> E = ets:new(t, []).
    +#Ref<0.1662103692.2407923716.214192>

    Command 42 creates an ETS table.

    43> ets:insert({d,1,2}).
     ** exception error: undefined function ets:insert/1

    Command 43 tries to insert a tuple into the ETS table, but the first argument -(the table) is missing. The exception kills the evaluator process.

    44> ets:insert(E, {d,1,2}).
    +(the table) is missing. The exception kills the evaluator process.

    44> ets:insert(E, {d,1,2}).
     ** exception error: argument is of wrong type
          in function  ets:insert/2
             called as ets:insert(16,{d,1,2})

    Command 44 corrects the mistake, but the ETS table has been destroyed as it was -owned by the killed evaluator process.

    45> f(E).
    +owned by the killed evaluator process.

    45> f(E).
     ok
    -46> catch_exception(true).
    +46> catch_exception(true).
     false

    Command 46 sets the exception handling of the evaluator process to true. The exception handling can also be set when starting Erlang by -erl -stdlib shell_catch_exception true.

    47> E = ets:new(t, []).
    +erl -stdlib shell_catch_exception true.

    47> E = ets:new(t, []).
     #Ref<0.1662103692.2407923716.214197>
    -48> ets:insert({d,1,2}).
    +48> ets:insert({d,1,2}).
     * exception error: undefined function ets:insert/1

    Command 48 makes the same mistake as in command 43, but this time the evaluator process lives on. The single star at the beginning of the printout signals that -the exception has been caught.

    49> ets:insert(E, {d,1,2}).
    -true

    Command 49 successfully inserts the tuple into the ETS table.

    50> ets:insert(#Ref<0.1662103692.2407923716.214197>, {e,3,4}).
    +the exception has been caught.

    49> ets:insert(E, {d,1,2}).
    +true

    Command 49 successfully inserts the tuple into the ETS table.

    50> ets:insert(#Ref<0.1662103692.2407923716.214197>, {e,3,4}).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/shell_default.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/shell_default.html	2026-08-21 04:00:30.229365103 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/shell_default.html	2026-08-21 04:00:30.228365097 +0000
    @@ -94,10 +94,10 @@
     
         

    Customizing the Erlang environment.

    The functions in this module are called when no module name is specified in a -shell command.

    Consider the following shell dialog:

    1> lists:reverse("abc").
    +shell command.

    Consider the following shell dialog:

    1> lists:reverse("abc").
     "cba"
    -2> c(foo).
    -{ok, foo}

    In command one, module lists is called. In command two, no module name is +2> c(foo). +{ok, foo}

    In command one, module lists is called. In command two, no module name is specified. The shell searches module user_default followed by module shell_default for function c/1.

    shell_default is intended for "system wide" customizations to the shell. user_default is intended for "local" or individual user customizations.

    Hint

    To add your own commands to the shell, create a module called user_default and /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/slave.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (979)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/slave.html 2026-08-21 04:00:30.249365234 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/slave.html 2026-08-21 04:00:30.251365247 +0000 @@ -340,7 +340,7 @@ at a master node. A pseudo server is an intermediary that only has the same registered name as the real server.

    For example, if you have started a slave node N and want to execute pxw graphics code on this node, you can start server pxw_server as a pseudo server -at the slave node. This is illustrated as follows:

    rpc:call(N, slave, pseudo, [node(), [pxw_server]]).
    +at the slave node. This is illustrated as follows:

    rpc:call(N, slave, pseudo, [node(), [pxw_server]]).
    @@ -494,9 +494,9 @@ passed to the new node and can be used for a variety of purposes; see erl(1).

    As an example, suppose that you want to start a slave node at host H with node name Name@H and want the slave node to have the following properties:

    • Directory Dir is to be added to the code path.
    • The Mnesia directory is to be set to M.
    • The Unix DISPLAY environment variable is to be set to the display of the -master node.

    The following code is executed to achieve this:

    E = " -env DISPLAY " ++ net_adm:localhost() ++ ":0 ",
    +master node.

    The following code is executed to achieve this:

    E = " -env DISPLAY " ++ net_adm:localhost() ++ ":0 ",
     Arg = "-mnesia_dir " ++ M ++ " -pa " ++ Dir ++ E,
    -slave:start(H, Name, Arg).

    The function returns {ok, Node}, where Node is the name of the new node, +slave:start(H, Name, Arg).

    The function returns {ok, Node}, where Node is the name of the new node, otherwise {error, Reason}, where Reason can be one of:

    • timeout - The master node failed to get in contact with the slave node. This can occur in a number of circumstances:

      • Erlang/OTP is not installed on the remote host.
      • The file system on the other host has a different structure to the the master.
      • The Erlang nodes have different cookies.
    • no_rsh - No remote shell program was found on the computer. Note that /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/sofs.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1348)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/sofs.html 2026-08-21 04:00:30.323365715 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/sofs.html 2026-08-21 04:00:30.323365715 +0000 @@ -227,16 +227,16 @@ selecting, duplicating, or rearranging parts of the elements.

    • Specifying a SetFun as an integer I is equivalent to specifying {external, fun(X) -> element(I, X) end}, but is to be preferred, as it makes it possible to handle this case even more efficiently.

    Examples of valid SetFuns:

    fun sofs:union/1
    -fun(S) -> sofs:partition(1, S) end
    -fun(S) -> sofs:from_term(sofs:no_elements(S)) end
    -{external, fun(A) -> A end}
    -{external, fun({A,_,C}) -> {C,A} end}
    -{external, fun({_,{_,C}}) -> C end}
    -{external, fun({_,{_,{_,E}=C}}) -> {E,{E,C}} end}
    +fun(S) -> sofs:partition(1, S) end
    +fun(S) -> sofs:from_term(sofs:no_elements(S)) end
    +{external, fun(A) -> A end}
    +{external, fun({A,_,C}) -> {C,A} end}
    +{external, fun({_,{_,C}}) -> C end}
    +{external, fun({_,{_,{_,E}=C}}) -> {E,{E,C}} end}
     2

    Examples of invalid SetFuns:

    fun sofs:no_elements/1
    -{external, fun(A) -> 2 * A end}
    -{external, fun({A,B,C}) -> A + B + C end}
    -{external, fun lists:sum/1}

    The order in which a SetFun is applied to the elements of an unordered set is +{external, fun(A) -> 2 * A end} +{external, fun({A,B,C}) -> A + B + C end} +{external, fun lists:sum/1}

    The order in which a SetFun is applied to the elements of an unordered set is not specified, and can change in future versions of this module.

    The execution time of the functions of this module is dominated by the time it takes to sort lists. When no sorting is needed, the execution time is in the worst case proportional to the sum of the sizes of the input arguments and the @@ -1742,9 +1742,9 @@

    Creates a function.

    a_function(F, T) is equivalent to -from_term(F, T) if the result is a function.

    Examples

    1> sofs:is_a_function(sofs:a_function([{1,a},{2,b},{3,c}])).
    +from_term(F, T) if the result is a function.

    Examples

    1> sofs:is_a_function(sofs:a_function([{1,a},{2,b},{3,c}])).
     true
    -2> sofs:a_function([{1,a},{1,b}]).
    +2> sofs:a_function([{1,a},{1,b}]).
     ** exception error: bad_function
          in function  sofs:a_function/1
    @@ -1779,10 +1779,10 @@ belongs to SetOfSets and E belongs to Set.

    If SetOfSets is a partition of a set X and R is the equivalence relation in X induced by SetOfSets, then the returned relation is the canonical map from X onto the equivalence classes with -respect to R.

    Examples

    1> Ss = sofs:from_term([[a,b],[b,c]]).
    -2> CR = sofs:canonical_relation(Ss).
    -3> sofs:to_external(CR).
    -[{a,[a,b]},{b,[a,b]},{b,[b,c]},{c,[b,c]}]
    +respect to R.

    Examples

    1> Ss = sofs:from_term([[a,b],[b,c]]).
    +2> CR = sofs:canonical_relation(Ss).
    +3> sofs:to_external(CR).
    +[{a,[a,b]},{b,[a,b]},{b,[b,c]},{c,[b,c]}]
    @@ -1812,12 +1812,12 @@

    Returns the composite of the functions Function1 and -Function2.

    Examples

    1> F1 = sofs:a_function([{a,1},{b,2},{c,2}]).
    -2> F2 = sofs:a_function([{1,x},{2,y},{3,z}]).
    -3> F = sofs:composite(F1, F2).
    -4> sofs:to_external(F).
    -[{a,x},{b,y},{c,y}]
    -5> sofs:composite(F2, F1).
    +Function2.

    Examples

    1> F1 = sofs:a_function([{a,1},{b,2},{c,2}]).
    +2> F2 = sofs:a_function([{1,x},{2,y},{3,z}]).
    +3> F = sofs:composite(F1, F2).
    +4> sofs:to_external(F).
    +[{a,x},{b,y},{c,y}]
    +5> sofs:composite(F2, F1).
     ** exception error: bad_function
          in function  sofs:composite/2
    @@ -1849,11 +1849,11 @@

    Creates the function that maps each element of set Set -onto AnySet.

    Examples

    1> S = sofs:set([a,b]).
    -2> E = sofs:from_term(1).
    -3> R = sofs:constant_function(S, E).
    -4> sofs:to_external(R).
    -[{a,1},{b,1}]
    +onto AnySet.

    Examples

    1> S = sofs:set([a,b]).
    +2> E = sofs:from_term(1).
    +3> R = sofs:constant_function(S, E).
    +4> sofs:to_external(R).
    +[{a,1},{b,1}]
    @@ -1882,10 +1882,10 @@

    Returns the converse of the binary relation BinRel1.

    See inverse/1 for a similar function that applies only to invertible -functions.

    Examples

    1> R1 = sofs:relation([{1,a},{2,b},{3,a}]).
    -2> R2 = sofs:converse(R1).
    -3> sofs:to_external(R2).
    -[{a,1},{a,3},{b,2}]
    +functions.

    Examples

    1> R1 = sofs:relation([{1,a},{2,b},{3,a}]).
    +2> R2 = sofs:converse(R1).
    +3> sofs:to_external(R2).
    +[{a,1},{a,3},{b,2}]
    @@ -1913,12 +1913,12 @@ -

    Returns the difference of the sets Set1 and Set2.

    Examples

    1> S0 = sofs:set([a,b,c,d]).
    -2> S1 = sofs:set([c,d,e,f]).
    -3> sofs:to_external(sofs:difference(S0, S1)).
    -[a,b]
    -4> sofs:to_external(sofs:difference(S1, S0)).
    -[e,f]
    +

    Returns the difference of the sets Set1 and Set2.

    Examples

    1> S0 = sofs:set([a,b,c,d]).
    +2> S1 = sofs:set([c,d,e,f]).
    +3> sofs:to_external(sofs:difference(S0, S1)).
    +[a,b]
    +4> sofs:to_external(sofs:difference(S1, S0)).
    +[e,f]
    @@ -1980,15 +1980,15 @@ a. It is assumed that Type is a valid type of the external set of the family.

    If G is a directed graph, it holds that the vertices and edges of G are the same as the vertices and edges of -family_to_digraph(digraph_to_family(G)).

    Examples

    1> G = digraph:new().
    -2> digraph:add_vertex(G, 1).
    -3> digraph:add_vertex(G, a).
    -4> digraph:add_vertex(G, b).
    -5> digraph:add_edge(G, 1, a).
    -6> digraph:add_edge(G, 1, b).
    -7> F = sofs:digraph_to_family(G).
    -8> sofs:to_external(F).
    -[{1,[a,b]},{a,[]},{b,[]}]
    +family_to_digraph(digraph_to_family(G)).

    Examples

    1> G = digraph:new().
    +2> digraph:add_vertex(G, 1).
    +3> digraph:add_vertex(G, a).
    +4> digraph:add_vertex(G, b).
    +5> digraph:add_edge(G, 1, a).
    +6> digraph:add_edge(G, 1, b).
    +7> F = sofs:digraph_to_family(G).
    +8> sofs:to_external(F).
    +[{1,[a,b]},{a,[]},{b,[]}]
    @@ -2016,10 +2016,10 @@ -

    Returns the domain of the binary relation BinRel.

    Examples

    1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]).
    -2> S = sofs:domain(R).
    -3> sofs:to_external(S).
    -[1,2]
    +

    Returns the domain of the binary relation BinRel.

    Examples

    1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]).
    +2> S = sofs:domain(R).
    +3> sofs:to_external(S).
    +[1,2]
    @@ -2049,11 +2049,11 @@

    Returns the difference between the binary relation BinRel1 and the -restriction of BinRel1 to Set.

    Examples

    1> R1 = sofs:relation([{1,a},{2,b},{3,c}]).
    -2> S = sofs:set([2,4,6]).
    -3> R2 = sofs:drestriction(R1, S).
    -4> sofs:to_external(R2).
    -[{1,a},{3,c}]

    drestriction(R, S) is equivalent to +restriction of BinRel1 to Set.

    Examples

    1> R1 = sofs:relation([{1,a},{2,b},{3,c}]).
    +2> S = sofs:set([2,4,6]).
    +3> R2 = sofs:drestriction(R1, S).
    +4> sofs:to_external(R2).
    +[{1,a},{3,c}]

    drestriction(R, S) is equivalent to difference(R, restriction(R, S)).

    @@ -2084,12 +2084,12 @@

    Returns a subset of Set1 containing those elements that do not give an element -in Set2 as the result of applying SetFun.

    Examples

    1> SetFun = {external, fun({_A,B,C}) -> {B,C} end}.
    -2> R1 = sofs:relation([{a,aa,1},{b,bb,2},{c,cc,3}]).
    -3> R2 = sofs:relation([{bb,2},{cc,3},{dd,4}]).
    -4> R3 = sofs:drestriction(SetFun, R1, R2).
    -5> sofs:to_external(R3).
    -[{a,aa,1}]

    drestriction(F, S1, S2) is equivalent to +in Set2 as the result of applying SetFun.

    Examples

    1> SetFun = {external, fun({_A,B,C}) -> {B,C} end}.
    +2> R1 = sofs:relation([{a,aa,1},{b,bb,2},{c,cc,3}]).
    +3> R2 = sofs:relation([{bb,2},{cc,3},{dd,4}]).
    +4> R3 = sofs:drestriction(SetFun, R1, R2).
    +5> sofs:to_external(R3).
    +[{a,aa,1}]

    drestriction(F, S1, S2) is equivalent to difference(S1, restriction(F, S1, S2)).

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/argparse.xhtml differs (HTML document, ASCII text, with very long lines (1338)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/argparse.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/argparse.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -35,20 +35,20 @@ example below is a fully functioning Erlang program accepting two command line arguments and printing their product.

    #!/usr/bin/env escript
     
    -main(Args) ->
    -    argparse:run(Args, cli(), #{progname => mul}).
    +main(Args) ->
    +    argparse:run(Args, cli(), #{progname => mul}).
     
    -cli() ->
    -    #{
    -        arguments => [
    -            #{name => left, type => integer},
    -            #{name => right, type => integer}
    -        ],
    +cli() ->
    +    #{
    +        arguments => [
    +            #{name => left, type => integer},
    +            #{name => right, type => integer}
    +        ],
             handler =>
    -            fun (#{left := Left, right := Right}) ->
    -                io:format("~b~n", [Left * Right])
    +            fun (#{left := Left, right := Right}) ->
    +                io:format("~b~n", [Left * Right])
                 end
    -    }.

    Running this script with no arguments results in an error, accompanied by the + }.

    Running this script with no arguments results in an error, accompanied by the usage information.

    The cli function defines a single command with embedded handler accepting a map. Keys of the map are argument names as defined by the argument field of the command, left and right in the example. Values are taken from the @@ -56,25 +56,25 @@ specification. Both arguments in the example above are required (and therefore defined as positional).

    Command hierarchy

    A command may contain nested commands, forming a hierarchy. Arguments defined at the upper level command are automatically added to all nested commands. Nested -commands example (assuming progname is nested):

    cli() ->
    -  #{
    +commands example (assuming progname is nested):

    cli() ->
    +  #{
         %% top level argument applicable to all commands
    -    arguments => [#{name => top}],
    -      commands => #{
    -        "first" => #{
    +    arguments => [#{name => top}],
    +      commands => #{
    +        "first" => #{
               %% argument applicable to "first" command and
               %%  all commands nested into "first"
    -          arguments => [#{name => mid}],
    -          commands => #{
    -            "second" => #{
    +          arguments => [#{name => mid}],
    +          commands => #{
    +            "second" => #{
                   %% argument only applicable for "second" command
    -              arguments => [#{name => bottom}],
    -              handler => fun (A) -> io:format("~p~n", [A]) end
    -          }
    -        }
    -      }
    -    }
    -  }.

    In the example above, a 3-level hierarchy is defined. First is the script itself + arguments => [#{name => bottom}], + handler => fun (A) -> io:format("~p~n", [A]) end + } + } + } + } + }.

    In the example above, a 3-level hierarchy is defined. First is the script itself (nested), accepting the only argument top. Since it has no associated handler, run/3 will not accept user input omitting nested command selection. For this example, user has to supply 5 arguments in the command line, two being @@ -86,14 +86,14 @@ on all operating systems). Both options and positional arguments have 1 or more associated values. See argument specification to find more details about supported combinations.

    In the user input, short options may be concatenated with their values. Long -options support values separated by =. Consider this definition:

    cli() ->
    -  #{
    -    arguments => [
    -      #{name => long, long => "-long"},
    -      #{name => short, short => $s}
    -    ],
    -    handler => fun (Args) -> io:format("~p~n", [Args]) end
    -  }.

    Running ./args --long=VALUE prints #{long => "VALUE"}, running +options support values separated by =. Consider this definition:

    cli() ->
    +  #{
    +    arguments => [
    +      #{name => long, long => "-long"},
    +      #{name => short, short => $s}
    +    ],
    +    handler => fun (Args) -> io:format("~p~n", [Args]) end
    +  }.

    Running ./args --long=VALUE prints #{long => "VALUE"}, running ./args -sVALUE prints #{short => "VALUE"}

    argparse supports boolean flags concatenation: it is possible to shorten -r -f -v to -rfv.

    Shortened option names are not supported: it is not possible to use --my-argum instead of --my-argument-name even when such option can be unambiguously @@ -513,111 +513,111 @@ which case resulting argument map will either contain the default value, or not have the key at all.

    • name - Sets the argument name in the parsed argument map. If help is not defined, name is also used to generate the default usage message.

    • short - Defines a short (single character) form of an optional argument.

      %% Define a command accepting argument named myarg, with short form $a:
      -1> Cmd = #{arguments => [#{name => myarg, short => $a}]}.
      +1> Cmd = #{arguments => [#{name => myarg, short => $a}]}.
       %% Parse command line "-a str":
      -2> {ok, ArgMap, _, _} = argparse:parse(["-a", "str"], Cmd), ArgMap.
      +2> {ok, ArgMap, _, _} = argparse:parse(["-a", "str"], Cmd), ArgMap.
       
      -#{myarg => "str"}
      +#{myarg => "str"}
       
       %% Option value can be concatenated with the switch: "-astr"
      -3> {ok, ArgMap, _, _} = argparse:parse(["-astr"], Cmd), ArgMap.
      +3> {ok, ArgMap, _, _} = argparse:parse(["-astr"], Cmd), ArgMap.
       
      -#{myarg => "str"}

      By default all options expect a single value following the option switch. The -only exception is an option of a boolean type.

    • long - Defines a long form of an optional argument.

      1> Cmd = #{arguments => [#{name => myarg, long => "name"}]}.
      +#{myarg => "str"}

      By default all options expect a single value following the option switch. The +only exception is an option of a boolean type.

    • long - Defines a long form of an optional argument.

      1> Cmd = #{arguments => [#{name => myarg, long => "name"}]}.
       %% Parse command line "-name Erlang":
      -2> {ok, ArgMap, _, _} = argparse:parse(["-name", "Erlang"], Cmd), ArgMap.
      +2> {ok, ArgMap, _, _} = argparse:parse(["-name", "Erlang"], Cmd), ArgMap.
       
      -#{myarg => "Erlang"}
      +#{myarg => "Erlang"}
       %% Or use "=" to separate the switch and the value:
      -3> {ok, ArgMap, _, _} = argparse:parse(["-name=Erlang"], Cmd), ArgMap.
      +3> {ok, ArgMap, _, _} = argparse:parse(["-name=Erlang"], Cmd), ArgMap.
       
      -#{myarg => "Erlang"}

      If neither short not long is defined, the argument is treated as +#{myarg => "Erlang"}

    If neither short not long is defined, the argument is treated as positional.

  • required - Forces the parser to expect the argument to be present in the command line. By default, all positional argument are required, and all options are not.

  • default - Specifies the default value to put in the parsed argument map -if the value is not supplied in the command line.

    1> argparse:parse([], #{arguments => [#{name => myarg, short => $m}]}).
    +if the value is not supplied in the command line.

    1> argparse:parse([], #{arguments => [#{name => myarg, short => $m}]}).
     
    -{ok,#{}, ...
    -2> argparse:parse([], #{arguments => [#{name => myarg, short => $m, default => "def"}]}).
    +{ok,#{}, ...
    +2> argparse:parse([], #{arguments => [#{name => myarg, short => $m, default => "def"}]}).
     
    -{ok,#{myarg => "def"}, ...
  • type - Defines type conversion and validation routine. The default is +{ok,#{myarg => "def"}, ...

  • type - Defines type conversion and validation routine. The default is string, assuming no conversion.

  • nargs - Defines the number of following arguments to consume from the command line. By default, the parser consumes the next argument and converts it into an Erlang term according to the specified type.

    • pos_integer/0 - Consume exactly this number of positional arguments, fail if there is not enough. Value in the argument map contains a list of exactly this length. Example, defining a positional argument expecting 3 -integer values:

      1> Cmd = #{arguments => [#{name => ints, type => integer, nargs => 3}]},
      -argparse:parse(["1", "2", "3"], Cmd).
      +integer values:

      1> Cmd = #{arguments => [#{name => ints, type => integer, nargs => 3}]},
      +argparse:parse(["1", "2", "3"], Cmd).
       
      -{ok, #{ints => [1, 2, 3]}, ...

      Another example defining an option accepted as -env and expecting two -string arguments:

      1> Cmd = #{arguments => [#{name => env, long => "env", nargs => 2}]},
      -argparse:parse(["-env", "key", "value"], Cmd).
      +{ok, #{ints => [1, 2, 3]}, ...

      Another example defining an option accepted as -env and expecting two +string arguments:

      1> Cmd = #{arguments => [#{name => env, long => "env", nargs => 2}]},
      +argparse:parse(["-env", "key", "value"], Cmd).
       
      -{ok, #{env => ["key", "value"]}, ...
    • list - Consume all following arguments until hitting the next option +{ok, #{env => ["key", "value"]}, ...

  • list - Consume all following arguments until hitting the next option (starting with an option prefix). May result in an empty list added to the -arguments map.

    1> Cmd = #{arguments => [
    -  #{name => nodes, long => "nodes", nargs => list},
    -  #{name => verbose, short => $v, type => boolean}
    -]},
    -argparse:parse(["-nodes", "one", "two", "-v"], Cmd).
    +arguments map.

    1> Cmd = #{arguments => [
    +  #{name => nodes, long => "nodes", nargs => list},
    +  #{name => verbose, short => $v, type => boolean}
    +]},
    +argparse:parse(["-nodes", "one", "two", "-v"], Cmd).
     
    -{ok, #{nodes => ["one", "two"], verbose => true}, ...
  • nonempty_list - Same as list, but expects at least one argument. +{ok, #{nodes => ["one", "two"], verbose => true}, ...

  • nonempty_list - Same as list, but expects at least one argument. Returns an error if the following command line argument is an option switch (starting with the prefix).

  • 'maybe' - Consumes the next argument from the command line, if it does not start with an option prefix. Otherwise, adds a default value to the -arguments map.

    1> Cmd = #{arguments => [
    -  #{name => level, short => $l, nargs => 'maybe', default => "error"},
    -  #{name => verbose, short => $v, type => boolean}
    -]},
    -argparse:parse(["-l", "info", "-v"], Cmd).
    +arguments map.

    1> Cmd = #{arguments => [
    +  #{name => level, short => $l, nargs => 'maybe', default => "error"},
    +  #{name => verbose, short => $v, type => boolean}
    +]},
    +argparse:parse(["-l", "info", "-v"], Cmd).
     
    -{ok,#{level => "info",verbose => true}, ...
    +{ok,#{level => "info",verbose => true}, ...
     
     %% When "info" is omitted, argument maps receives the default "error"
    -2> argparse:parse(["-l", "-v"], Cmd).
    +2> argparse:parse(["-l", "-v"], Cmd).
     
    -{ok,#{level => "error",verbose => true}, ...
  • {'maybe', term()} - Consumes the next argument from the command line, +{ok,#{level => "error",verbose => true}, ...

  • {'maybe', term()} - Consumes the next argument from the command line, /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/array.xhtml differs (HTML document, ASCII text, with very long lines (2373)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/array.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/array.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -30,14 +30,14 @@ reset/2). If you need to differentiate between unset and set entries, ensure that the default value cannot be confused with the values of set entries.

    The array never shrinks automatically. If an index I has been used to set an entry successfully, all indices in the range [0,I] stay accessible unless the -array size is explicitly changed by calling resize/2.

    Examples:

    Create a fixed-size array with entries 0-9 set to undefined:

    A0 = array:new(10).
    -10 = array:size(A0).

    Create an extendible array and set entry 17 to true, causing the array to grow -automatically:

    A1 = array:set(17, true, array:new()).
    -18 = array:size(A1).

    Read back a stored value:

    true = array:get(17, A1).

    Accessing an unset entry returns default value:

    undefined = array:get(3, A1)

    Accessing an entry beyond the last set entry also returns the default value, if -the array does not have fixed size:

    undefined = array:get(18, A1).

    "Sparse" functions ignore default-valued entries:

    A2 = array:set(4, false, A1).
    -[{4, false}, {17, true}] = array:sparse_to_orddict(A2).

    An extendible array can be made fixed-size later:

    A3 = array:fix(A2).

    A fixed-size array does not grow automatically and does not allow accesses -beyond the last set entry:

    {'EXIT',{badarg,_}} = (catch array:set(18, true, A3)).
    -{'EXIT',{badarg,_}} = (catch array:get(18, A3)).
    +array size is explicitly changed by calling resize/2.

    Examples:

    Create a fixed-size array with entries 0-9 set to undefined:

    A0 = array:new(10).
    +10 = array:size(A0).

    Create an extendible array and set entry 17 to true, causing the array to grow +automatically:

    A1 = array:set(17, true, array:new()).
    +18 = array:size(A1).

    Read back a stored value:

    true = array:get(17, A1).

    Accessing an unset entry returns default value:

    undefined = array:get(3, A1)

    Accessing an entry beyond the last set entry also returns the default value, if +the array does not have fixed size:

    undefined = array:get(18, A1).

    "Sparse" functions ignore default-valued entries:

    A2 = array:set(4, false, A1).
    +[{4, false}, {17, true}] = array:sparse_to_orddict(A2).

    An extendible array can be made fixed-size later:

    A3 = array:fix(A2).

    A fixed-size array does not grow automatically and does not allow accesses +beyond the last set entry:

    {'EXIT',{badarg,_}} = (catch array:set(18, true, A3)).
    +{'EXIT',{badarg,_}} = (catch array:get(18, A3)).
    @@ -1062,7 +1062,7 @@ array size; this also implies {fixed, true}. If N is not a non-negative integer, the call fails with reason badarg.

  • fixed or {fixed, true} - Creates a fixed-size array. See also fix/1.

  • {fixed, false} - Creates an extendible (non-fixed-size) array.

  • {default, Value} - Sets the default value for the array to Value.

  • Options are processed in the order they occur in the list, that is, later options have higher precedence.

    The default value is used as the value of uninitialized entries, and cannot be -changed once the array has been created.

    Examples:

    array:new(100)

    creates a fixed-size array of size 100.

    array:new({default,0})

    creates an empty, extendible array whose default value is 0.

    array:new([{size,10},{fixed,false},{default,-1}])

    creates an extendible array with initial size 10 whose default value is -1.

    See also fix/1, from_list/2, get/2, new/0, new/2, set/3.

    +changed once the array has been created.

    Examples:

    array:new(100)

    creates a fixed-size array of size 100.

    array:new({default,0})

    creates an empty, extendible array whose default value is 0.

    array:new([{size,10},{fixed,false},{default,-1}])

    creates an extendible array with initial size 10 whose default value is -1.

    See also fix/1, from_list/2, get/2, new/0, new/2, set/3.

    @@ -1095,7 +1095,7 @@ Options override parameter Size.

    If Options is a list, this is equivalent to new([{size, Size} | Options]), otherwise it is equivalent to new([{size, Size} | [Options]]). However, using this function -directly is more efficient.

    Example:

    array:new(100, {default,0})

    creates a fixed-size array of size 100, whose default value is 0.

    See also new/1.

    +directly is more efficient.

    Example:

    array:new(100, {default,0})

    creates a fixed-size array of size 100, whose default value is 0.

    See also new/1.

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/assert_hrl.xhtml differs (HTML document, ASCII text, with very long lines (1299)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/assert_hrl.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/assert_hrl.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -18,7 +18,7 @@

    assert.hrl

    Assert macros.

    Description

    The include file assert.hrl provides macros for inserting assertions in your -program code.

    Include the following directive in the module from which the function is called:

    -include_lib("stdlib/include/assert.hrl").

    When an assertion succeeds, the assert macro yields the atom ok. When an +program code.

    Include the following directive in the module from which the function is called:

    -include_lib("stdlib/include/assert.hrl").

    When an assertion succeeds, the assert macro yields the atom ok. When an assertion fails, an exception of type error is generated. The associated error term has the form {Macro, Info}. Macro is the macro name, for example, assertEqual. Info is a list of tagged values, such as @@ -40,7 +40,7 @@ use ASSERT/NOASSERT to control only the assert macros.

    Macros

    • assert(BoolExpr)

    • assert(BoolExpr, Comment) - Tests that BoolExpr completes normally returning true.

    • assertNot(BoolExpr)

    • assertNot(BoolExpr, Comment) - Tests that BoolExpr completes normally returning false.

    • assertMatch(GuardedPattern, Expr)

    • assertMatch(GuardedPattern, Expr, Comment) - Tests that Expr completes -normally yielding a value that matches GuardedPattern, for example:

      ?assertMatch({bork, _}, f())

      Notice that a guard when ... can be included:

      ?assertMatch({bork, X} when X > 0, f())
    • assertNotMatch(GuardedPattern, Expr)

    • assertNotMatch(GuardedPattern, Expr, Comment) - Tests that Expr +normally yielding a value that matches GuardedPattern, for example:

      ?assertMatch({bork, _}, f())

      Notice that a guard when ... can be included:

      ?assertMatch({bork, X} when X > 0, f())
    • assertNotMatch(GuardedPattern, Expr)

    • assertNotMatch(GuardedPattern, Expr, Comment) - Tests that Expr completes normally yielding a value that does not match GuardedPattern.

      As in assertMatch, GuardedPattern can have a when part.

    • assertEqual(ExpectedValue, Expr)

    • assertEqual(ExpectedValue, Expr, Comment) - Tests that Expr completes normally yielding a value that is exactly equal to ExpectedValue.

    • assertNotEqual(ExpectedValue, Expr)

    • assertNotEqual(ExpectedValue, Expr, Comment) - Tests that Expr completes normally yielding a value that is not exactly equal to /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/base64.xhtml differs (HTML document, ASCII text, with very long lines (634)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/base64.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/base64.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -549,16 +549,16 @@

      Decodes a base64 string encoded using the standard alphabet according to RFC 4648 Section 4 to plain ASCII.

      The function will strip away any whitespace characters and check for the -the correct number of = padding characters at the end of the encoded string.

      See decode_options/0 for details on which options can be passed.

      Example:

      1> base64:decode("AQIDBA==").
      -<<1,2,3,4>>
      -2> base64:decode("AQ ID BA==").
      -<<1,2,3,4>>
      -3> base64:decode("AQIDBA=").
      +the correct number of = padding characters at the end of the encoded string.

      See decode_options/0 for details on which options can be passed.

      Example:

      1> base64:decode("AQIDBA==").
      +<<1,2,3,4>>
      +2> base64:decode("AQ ID BA==").
      +<<1,2,3,4>>
      +3> base64:decode("AQIDBA=").
       ** exception error: missing_padding
            in function  base64:decode_list/7 (base64.erl, line 734)
               *** data to decode is missing final = padding characters, if this is intended, use the `padding => false` option
      -4> base64:decode("AQIDBA=", #{ padding => false }).
      -<<1,2,3,4>>
      +4>
      base64:decode("AQIDBA=", #{ padding => false }). +<<1,2,3,4>>
    @@ -812,10 +812,10 @@

    Decodes a base64 "mime" string encoded using the standard alphabet according to RFC 4648 Section 4 to plain ASCII.

    The function will strip away any illegal characters. It does not check for the -the correct number of = padding characters at the end of the encoded string.

    See decode_options/0 for details on which options can be passed.

    Example:

    1> base64:mime_decode("AQIDBA==").
    -<<1,2,3,4>>
    -2> base64:mime_decode("AQIDB=A=").
    -<<1,2,3,4>>
    +the correct number of = padding characters at the end of the encoded string.

    See decode_options/0 for details on which options can be passed.

    Example:

    1> base64:mime_decode("AQIDBA==").
    +<<1,2,3,4>>
    +2> base64:mime_decode("AQIDB=A=").
    +<<1,2,3,4>>
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/beam_lib.xhtml differs (HTML document, ASCII text, with very long lines (1372)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/beam_lib.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/beam_lib.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -33,8 +33,8 @@ Tools such as Debugger and Xref require the debug information to be included.

    Warning

    Source code can be reconstructed from the debug information. To prevent this, use encrypted debug information (see below).

    The debug information can also be removed from BEAM files using strip/1, strip_files/1, and/or strip_release/1.

    Reconstruct Source Code

    The following example shows how to reconstruct Erlang source code from the debug -information in a BEAM file Beam:

    {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(Beam,[abstract_code]).
    -io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).

    Encrypted Debug Information

    The debug information can be encrypted to keep the source code secret, but still +information in a BEAM file Beam:

    {ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(Beam,[abstract_code]).
    +io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).

    Encrypted Debug Information

    The debug information can be encrypted to keep the source code secret, but still be able to use tools such as Debugger or Xref.

    To use encrypted debug information, a key must be provided to the compiler and beam_lib. The key is specified as a string. It is recommended that the string contains at least 32 characters and that both upper and lower case letters as @@ -54,13 +54,13 @@ user's home directory and then filename:basedir(user_config, "erlang"). If the file is found and contains a key, beam_lib implicitly creates a crypto key fun -and registers it.

    File .erlang.crypt is to contain a single list of tuples:

    {debug_info, Mode, Module, Key}

    Mode is the type of crypto algorithm; currently, the only allowed value is +and registers it.

    File .erlang.crypt is to contain a single list of tuples:

    {debug_info, Mode, Module, Key}

    Mode is the type of crypto algorithm; currently, the only allowed value is des3_cbc. Module is either an atom, in which case Key is only used for the module Module, or [], in which case Key is used for all modules. Key is the non-empty key string.

    Key in the first tuple where both Mode and Module match is used.

    The following is an example of an .erlang.crypt file that returns the same key -for all modules:

    [{debug_info, des3_cbc, [], "%>7}|pc/DM6Cga*68$Mw]L#&_Gejr]G^"}].

    The following is a slightly more complicated example of an .erlang.crypt -providing one key for module t and another key for all other modules:

    [{debug_info, des3_cbc, t, "My KEY"},
    - {debug_info, des3_cbc, [], "%>7}|pc/DM6Cga*68$Mw]L#&_Gejr]G^"}].

    Note

    Do not use any of the keys in these examples. Use your own keys.

    +for all modules:

    [{debug_info, des3_cbc, [], "%>7}|pc/DM6Cga*68$Mw]L#&_Gejr]G^"}].

    The following is a slightly more complicated example of an .erlang.crypt +providing one key for module t and another key for all other modules:

    [{debug_info, des3_cbc, t, "My KEY"},
    + {debug_info, des3_cbc, [], "%>7}|pc/DM6Cga*68$Mw]L#&_Gejr]G^"}].

    Note

    Do not use any of the keys in these examples. Use your own keys.

    @@ -1451,11 +1451,11 @@

    Registers an unary fun that is called if beam_lib must read an debug_info chunk that has been encrypted. The fun is held in a process that is started by the function.

    If a fun is already registered when attempting to register a fun, -{error, exists} is returned.

    The fun must handle the following arguments:

    CryptoKeyFun(init) -> ok | {ok, NewCryptoKeyFun} | {error, Term}

    Called when the fun is registered, in the process that holds the fun. Here the +{error, exists} is returned.

    The fun must handle the following arguments:

    CryptoKeyFun(init) -> ok | {ok, NewCryptoKeyFun} | {error, Term}

    Called when the fun is registered, in the process that holds the fun. Here the crypto key fun can do any necessary initializations. If {ok, NewCryptoKeyFun} is returned, NewCryptoKeyFun is registered instead of CryptoKeyFun. If {error, Term} is returned, the registration is aborted and -crypto_key_fun/1 also returns {error, Term}.

    CryptoKeyFun({debug_info, Mode, Module, Filename}) -> Key

    Called when the key is needed for module Module in the file named Filename. +crypto_key_fun/1 also returns {error, Term}.

    CryptoKeyFun({debug_info, Mode, Module, Filename}) -> Key

    Called when the key is needed for module Module in the file named Filename. Mode is the type of crypto algorithm; currently, the only possible value is des3_cbc. The call is to fail (raise an exception) if no key is available.

    CryptoKeyFun(clear) -> term()

    Called before the fun is unregistered. Here any cleaning up can be done. The return value is not important, but is passed back to the caller of @@ -1822,14 +1822,14 @@ -vsn(Vsn).

    If this attribute is not specified, the version defaults to the checksum of the module. Notice that if version Vsn is not a list, it is made into one, that is {ok,{Module,[Vsn]}} is returned. If there are many -vsn -module attributes, the result is the concatenated list of versions.

    Examples:

    1> beam_lib:version(a). % -vsn(1).
    -{ok,{a,[1]}}
    -2> beam_lib:version(b). % -vsn([1]).
    -{ok,{b,[1]}}
    -3> beam_lib:version(c). % -vsn([1]). -vsn(2).
    -{ok,{c,[1,2]}}
    -4> beam_lib:version(d). % no -vsn attribute
    -{ok,{d,[275613208176997377698094100858909383631]}}
    +module attributes, the result is the concatenated list of versions.

    Examples:

    1> beam_lib:version(a). % -vsn(1).
    +{ok,{a,[1]}}
    +2> beam_lib:version(b). % -vsn([1]).
    +{ok,{b,[1]}}
    +3> beam_lib:version(c). % -vsn([1]). -vsn(2).
    +{ok,{c,[1,2]}}
    +4> beam_lib:version(d). % no -vsn attribute
    +{ok,{d,[275613208176997377698094100858909383631]}}
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/binary.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1581)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/binary.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/binary.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -502,11 +502,11 @@

    Returns the byte at position Pos (zero-based) in binary Subject as an integer.

    If Pos >= byte_size(Subject), a badarg exception -is raised.

    Examples

    1> binary:at(<<5,19,72,33>>, 0).
    +is raised.

    Examples

    1> binary:at(<<5,19,72,33>>, 0).
     5
    -2> binary:at(<<5,19,72,33>>, 1).
    +2> binary:at(<<5,19,72,33>>, 1).
     19
    -3> binary:at(<<5,19,72,33>>, 4).
    +3> binary:at(<<5,19,72,33>>, 4).
     ** exception error: bad argument
          in function  binary:at/2
             called as binary:at(<<5,19,72,33>>,4)
    @@ -540,8 +540,8 @@

    Converts Subject to a list of byte()s, each -representing the value of one byte.

    Examples

    1> binary:bin_to_list(<<"erlang",0>>).
    -[101,114,108,97,110,103,0]
    +representing the value of one byte.

    Examples

    1> binary:bin_to_list(<<"erlang",0>>).
    +[101,114,108,97,110,103,0]
    @@ -603,10 +603,10 @@

    Converts part of Subject to a list of byte/0s, each representing -the value of one byte.

    Pos and Len denote which part of the Subject binary to convert.

    Examples

    1> binary:bin_to_list(<<"erlang">>, 1, 3).
    +the value of one byte.

    Pos and Len denote which part of the Subject binary to convert.

    Examples

    1> binary:bin_to_list(<<"erlang">>, 1, 3).
     "rla"
     %% or [114,108,97] in list notation.
    -2> binary:bin_to_list(<<"erlang">>, 5, 3).
    +2> binary:bin_to_list(<<"erlang">>, 5, 3).
     ** exception error: bad argument
          in function  binary:bin_to_list/3
             called as binary:bin_to_list(<<"erlang">>,5,3)
    @@ -653,9 +653,9 @@
     binary is specified, the set has only one element. The order of alternatives in
     a pattern is not significant.

    The list of binaries used for search alternatives must be flat, proper, and non-empty.

    If Pattern is not a binary or a flat proper non-empty list of binaries with -length greater than 0, a badarg exception is raised.

    Examples

    1> Pat = binary:compile_pattern(~"rain").
    -2> binary:match(~"the rain in spain", Pat).
    -{4,4}
    +length greater than 0, a badarg exception is raised.

    Examples

    1> Pat = binary:compile_pattern(~"rain").
    +2> binary:match(~"the rain in spain", Pat).
    +{4,4}
    @@ -692,13 +692,13 @@ more binary data than needed. In general, sharing binary data is beneficial.

    Only in special cases — when small parts reference large binaries and the large binaries are no longer used in any process — can deliberate copying be -beneficial.

    Examples

    1> HugeBinary = <<0:100_000/unit:8>>.
    -2> byte_size(HugeBinary).
    +beneficial.

    Examples

    1> HugeBinary = <<0:100_000/unit:8>>.
    +2> byte_size(HugeBinary).
     100000
    -3> Part = binary:part(HugeBinary, 0, 5).
    -<<0,0,0,0,0>>
    -4> Copy = binary:copy(Part).
    -<<0,0,0,0,0>>
    +3>
    Part = binary:part(HugeBinary, 0, 5). +<<0,0,0,0,0>> +4> Copy = binary:copy(Part). +<<0,0,0,0,0>>
    @@ -728,8 +728,8 @@ -

    Creates a binary with the content of Subject duplicated N times.

    This function always creates a new binary, even when N is 1.

    Examples

    1> binary:copy(~"-", 10).
    -<<"----------">>
    +

    Creates a binary with the content of Subject duplicated N times.

    This function always creates a new binary, even when N is 1.

    Examples

    1> binary:copy(~"-", 10).
    +<<"----------">>
    @@ -760,9 +760,9 @@

    Decodes a hex-encoded binary into a binary.

    An exception is raised if the size of the binary is not evenly divisble by two, -or if the binary contains any characters that do not represent hex digits.

    Examples

    1> binary:decode_hex(<<"666f6f">>).
    -<<"foo">>
    -2> binary:decode_hex(<<"A">>).
    +or if the binary contains any characters that do not represent hex digits.

    Examples

    1> binary:decode_hex(<<"666f6f">>).
    +<<"foo">>
    +2> binary:decode_hex(<<"A">>).
     ** exception error: bad argument
          in function  binary:decode_hex/1
             called as binary:decode_hex(<<"A">>)
    @@ -831,15 +831,15 @@
           
     
     

    Converts the binary digit representation, in big endian or little endian, of a -positive integer in Subject to an Erlang integer/0.

    Examples

    1> binary:decode_unsigned(<<7>>).
    +positive integer in Subject to an Erlang integer/0.

    Examples

    1> binary:decode_unsigned(<<7>>).
     7
    -2> binary:decode_unsigned(<<1,0>>).
    +2> binary:decode_unsigned(<<1,0>>).
     256
    -3> binary:decode_unsigned(<<169,138,199>>).
    +3> binary:decode_unsigned(<<169,138,199>>).
     11111111
    -4> binary:decode_unsigned(<<169,138,199>>, big).
    +4> binary:decode_unsigned(<<169,138,199>>, big).
     11111111
    -5> binary:decode_unsigned(<<169,138,199>>, little).
    +5> binary:decode_unsigned(<<169,138,199>>, little).
     13077161
    @@ -902,12 +902,12 @@

    Encodes a binary into a hex-encoded binary using the specified case for the -hexadecimal digits "a" to "f".

    Examples

    1> binary:encode_hex(<<"foo">>, uppercase).
    -<<"666F6F">>
    -2> binary:encode_hex(<<"/">>, uppercase).
    -<<"2F">>
    -3> binary:encode_hex(<<"/">>, lowercase).
    -<<"2f">>
    +hexadecimal digits "a" to "f".

    Examples

    1> binary:encode_hex(<<"foo">>, uppercase).
    +<<"666F6F">>
    +2> binary:encode_hex(<<"/">>, uppercase).
    +<<"2F">>
    +3> binary:encode_hex(<<"/">>, lowercase).
    +<<"2f">>
    @@ -970,18 +970,18 @@

    Converts a non-negative integer into the smallest possible unsigned binary representation, using either big-endian or little-endian format.

    If Unsigned is not a non-negative integer, a badarg exception is -raised.

    Examples

    1> binary:encode_unsigned(0, big).
    -<<0>>
    -2> binary:encode_unsigned(255, big).
    -<<255>>
    -3> binary:encode_unsigned(256, big).
    -<<1,0>>
    -4> binary:encode_unsigned(256, little).
    -<<0,1>>
    -5> binary:encode_unsigned(11111111, big).
    -<<169,138,199>>
    -6> binary:encode_unsigned(11111111, little).
    -<<199,138,169>>
    +raised.

    Examples

    1> binary:encode_unsigned(0, big).
    +<<0>>
    +2> binary:encode_unsigned(255, big).
    +<<255>>
    +3> binary:encode_unsigned(256, big).
    +<<1,0>>
    +4> binary:encode_unsigned(256, little).
    +<<0,1>>
    +5> binary:encode_unsigned(11111111, big).
    +<<169,138,199>>
    +6> binary:encode_unsigned(11111111, little).
    +<<199,138,169>>
    @@ -1011,9 +1011,9 @@ -

    Returns the first byte of binary Subject as an integer.

    If the size of Subject is zero, a badarg exception is raised.

    Examples

    1> binary:first(<<42,99,100>>).
    +

    Returns the first byte of binary Subject as an integer.

    If the size of Subject is zero, a badarg exception is raised.

    Examples

    1> binary:first(<<42,99,100>>).
     42
    -2> binary:first(<<>>).
    +2> binary:first(<<>>).
     ** exception error: bad argument
          in function  binary:first/1
             called as binary:first(<<>>)
    @@ -1047,8 +1047,8 @@
     
           
     
    -

    Joins a list of binaries together by a specified Separator.

    Equivalent to iolist_to_binary(lists:join(Separator, Binaries)), but faster.

    Examples

    1> binary:join([<<"a">>, <<"b">>, <<"c">>], <<", ">>).
    -<<"a, b, c">>
    +

    Joins a list of binaries together by a specified Separator.

    Equivalent to iolist_to_binary(lists:join(Separator, Binaries)), but faster.

    Examples

    1> binary:join([<<"a">>, <<"b">>, <<"c">>], <<", ">>).
    +<<"a, b, c">>
    @@ -1078,9 +1078,9 @@ -

    Returns the last byte of binary Subject as an integer.

    If the size of Subject is zero, a badarg exception is raised.

    Examples

    1> binary:last(<<42,99,100>>).
    +

    Returns the last byte of binary Subject as an integer.

    If the size of Subject is zero, a badarg exception is raised.

    Examples

    1> binary:last(<<42,99,100>>).
     100
    -2> binary:last(<<>>).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/calendar.xhtml differs (HTML document, ASCII text, with very long lines (454))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/calendar.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/calendar.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -1816,13 +1816,13 @@
     

    Converts an RFC 3339 timestamp into system time. The data format of RFC 3339 timestamps is described by RFC 3339. Starting from OTP 25.1, the minutes part of the time zone is optional.

    Valid option:

    • {unit, Unit} - The time unit of the return value. The default is -second.
    1> calendar:rfc3339_to_system_time("2018-02-01T16:17:58+01:00").
    +second.
    1> calendar:rfc3339_to_system_time("2018-02-01T16:17:58+01:00").
     1517498278
    -2> calendar:rfc3339_to_system_time("2018-02-01 15:18:02.088Z",
    -   [{unit, nanosecond}]).
    +2> calendar:rfc3339_to_system_time("2018-02-01 15:18:02.088Z",
    +   [{unit, nanosecond}]).
     1517498282088000000
    -3> calendar:rfc3339_to_system_time(<<"2018-02-01 15:18:02.088Z">>,
    -   [{unit, nanosecond}]).
    +3> calendar:rfc3339_to_system_time(<<"2018-02-01 15:18:02.088Z">>,
    +   [{unit, nanosecond}]).
     1517498282088000000
    @@ -1994,20 +1994,20 @@ second digits is three, six, or nine depending on what time unit is chosen. For native three fractional digits are included. Notice that trailing zeros are not removed from the fraction.

  • {return, Return} - The desired encoding type for the output, -whether a string or a binary is desired. Defaults to string.

  • 1> calendar:system_time_to_rfc3339(erlang:system_time(second)).
    +whether a string or a binary is desired. Defaults to string.

    1> calendar:system_time_to_rfc3339(erlang:system_time(second)).
     "2018-04-23T14:56:28+02:00"
    -2> calendar:system_time_to_rfc3339(erlang:system_time(second),
    -   [{offset, "-02:00"}]).
    +2> calendar:system_time_to_rfc3339(erlang:system_time(second),
    +   [{offset, "-02:00"}]).
     "2018-04-23T10:56:52-02:00"
    -3> calendar:system_time_to_rfc3339(erlang:system_time(second),
    -   [{offset, -7200}]).
    +3> calendar:system_time_to_rfc3339(erlang:system_time(second),
    +   [{offset, -7200}]).
     "2018-04-23T10:57:05-02:00"
    -4> calendar:system_time_to_rfc3339(erlang:system_time(millisecond),
    -   [{unit, millisecond}, {time_designator, $\s}, {offset, "Z"}]).
    +4> calendar:system_time_to_rfc3339(erlang:system_time(millisecond),
    +   [{unit, millisecond}, {time_designator, $\s}, {offset, "Z"}]).
     "2018-04-23 12:57:20.482Z"
    -5> calendar:system_time_to_rfc3339(erlang:system_time(millisecond),
    -   [{unit, millisecond}, {time_designator, $\s}, {offset, "Z"}, {return, binary}]).
    -<<"2018-04-23 12:57:20.482Z">>
    +5>
    calendar:system_time_to_rfc3339(erlang:system_time(millisecond), + [{unit, millisecond}, {time_designator, $\s}, {offset, "Z"}, {return, binary}]). +<<"2018-04-23 12:57:20.482Z">>
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> stdlib - 7.3.0.1 - urn:uuid:fc056493-7e7f-2cca-fe13-55b74cda6f26 + urn:uuid:64a86f88-7689-290d-cf58-67f6fe04737c en - 2026-08-21T03:47:18Z + 2042-09-22T17:05:50Z /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/custom_shell.xhtml differs (HTML document, ASCII text, with very long lines (1276)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/custom_shell.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/custom_shell.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -32,20 +32,20 @@ started by default in -noshell mode, so we don't have to do anything special here. To start the custom shell we then call shell:start_interactive/1.

    #!/usr/bin/env escript
     %% pshell.es
    --export([start/0]).
    -main(_Args) ->
    -    shell:start_interactive({?MODULE, start, []}),
    -    timer:sleep(infinity). %% Make sure the escript does not exit
    +-export([start/0]).
    +main(_Args) ->
    +    shell:start_interactive({?MODULE, start, []}),
    +    timer:sleep(infinity). %% Make sure the escript does not exit
     
    --spec start() -> pid().
    -start() ->
    -    spawn(fun() ->
    -                  io:format(~"Starting process inspection shell~n"),
    -                  loop()
    -          end).
    +-spec start() -> pid().
    +start() ->
    +    spawn(fun() ->
    +                  io:format(~"Starting process inspection shell~n"),
    +                  loop()
    +          end).
     
    -loop() ->
    -    receive _M -> loop() end.

    If we run the above we will get this:

    $ ./pshell.es
    +loop() ->
    +    receive _M -> loop() end.

    If we run the above we will get this:

    $ ./pshell.es
     Erlang/OTP 28 [DEVELOPMENT] [erts-15.0.1] [source-b395339a02] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
     
     Starting process inspection shell
    @@ -56,32 +56,32 @@
     io:standard_io/0 as this shell will be line based. However, for a more complex
     shell it is better to send get_until I/O requests
     as commands read that way can span multiple lines. So we expand our loop/0 with
    -a io:get_line/1 and pass the results to our parser.

    loop() ->
    -    case io:get_line("> ") of
    +a io:get_line/1 and pass the results to our parser.

    loop() ->
    +    case io:get_line("> ") of
             eof -> ok;
    -        {error, Reason} -> exit(Reason);
    -        Data -> eval(string:trim(Data))
    +        {error, Reason} -> exit(Reason);
    +        Data -> eval(string:trim(Data))
         end,
    -    loop().
    +    loop().
     
    -eval("list") ->
    +eval("list") ->
         Format = " ~.10ts | ~.10ts | ~.10ts~n",
    -    io:format(Format,["Pid", "Name", "MsgQ Len"]),
    -    [begin
    -         [{registered_name,Name},{message_queue_len,Len}]
    -             = erlang:process_info(Pid, [registered_name, message_queue_len]),
    -         io:format(Format,[to_list(Pid), to_list(Name), to_list(Len)])
    -     end || Pid <- processes()];
    -eval(Unknown) ->
    -    io:format("Unknown command: '~ts'~n",[Unknown]).
    +    io:format(Format,["Pid", "Name", "MsgQ Len"]),
    +    [begin
    +         [{registered_name,Name},{message_queue_len,Len}]
    +             = erlang:process_info(Pid, [registered_name, message_queue_len]),
    +         io:format(Format,[to_list(Pid), to_list(Name), to_list(Len)])
    +     end || Pid <- processes()];
    +eval(Unknown) ->
    +    io:format("Unknown command: '~ts'~n",[Unknown]).
     
    -to_list(Pid) when is_pid(Pid) ->
    -    pid_to_list(Pid);
    -to_list(Atom) when is_atom(Atom) ->
    -    atom_to_list(Atom);
    -to_list(Int) when is_integer(Int) ->
    -    integer_to_list(Int);
    -to_list(List) when is_list(List) ->
    +to_list(Pid) when is_pid(Pid) ->
    +    pid_to_list(Pid);
    +to_list(Atom) when is_atom(Atom) ->
    +    atom_to_list(Atom);
    +to_list(Int) when is_integer(Int) ->
    +    integer_to_list(Int);
    +to_list(List) when is_list(List) ->
         List.

    If we run the above we will get this:

    $ ./pshell.es
     Erlang/OTP 28 [DEVELOPMENT] [erts-15.0.1] [source-b395339a02] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
     
    @@ -101,56 +101,56 @@
      <0.11.0>   | erl_prim_l | 0         
      <0.43.0>   | logger     | 0         
      <0.45.0>   | applicatio | 0
    -...

    With this all in place we can now easily add inspect, suspend and resume as well.

    eval("inspect " ++ PidStr) ->
    -    case parse_pid(PidStr) of
    +...

    With this all in place we can now easily add inspect, suspend and resume as well.

    eval("inspect " ++ PidStr) ->
    +    case parse_pid(PidStr) of
             invalid -> ok;
             Pid ->
    -            [{registered_name, Name}, {memory, Memory}, {messages, Messages}, {status, Status}] =
    -                erlang:process_info(Pid, [registered_name, memory, messages, status]),
    -            io:format("Pid: ~p~nName: ~ts~nStatus: ~p~nMemory: ~p~nMessages: ~p~n",
    -                      [Pid, to_list(Name), Status, Memory, Messages])
    +            [{registered_name, Name}, {memory, Memory}, {messages, Messages}, {status, Status}] =
    +                erlang:process_info(Pid, [registered_name, memory, messages, status]),
    +            io:format("Pid: ~p~nName: ~ts~nStatus: ~p~nMemory: ~p~nMessages: ~p~n",
    +                      [Pid, to_list(Name), Status, Memory, Messages])
         end;
    -eval("suspend " ++ PidStr) ->
    -    case parse_pid(PidStr) of
    +eval("suspend " ++ PidStr) ->
    +    case parse_pid(PidStr) of
             invalid -> ok;
             Pid ->
    -            erlang:suspend_process(Pid),
    -            io:format("Suspeneded ~ts~n")
    +            erlang:suspend_process(Pid),
    +            io:format("Suspeneded ~ts~n")
         end;
    -eval("resume " ++ PidStr) ->
    -    case parse_pid(PidStr) of
    +eval("resume " ++ PidStr) ->
    +    case parse_pid(PidStr) of
             invalid -> ok;
             Pid ->
    -            erlang:resumne_process(Pid),
    -            io:format("Resumed ~ts~n")
    +            erlang:resumne_process(Pid),
    +            io:format("Resumed ~ts~n")
         end;

    Adding autocompletion

    Wouldn't it be great if we could add some simple auto-completion for our shell? We can do that by setting a edlin_expand fun for our shell. This is done by calling io:setopts([{expand_fun, Fun}]). The fun that we provide is will receive the reversed current line from edlin and is expected to return possible expansions. Let's start by adding a simple fun to -expand our commands.

    -spec start() -> pid().
    -start() ->
    -    spawn(fun() ->
    -                  io:setopts([{expand_fun, fun expand_fun/1}]),
    -                  io:format(~"Starting process inspection shell~n"),
    -                  loop()
    -          end).
    +expand our commands.

    -spec start() -> pid().
    +start() ->
    +    spawn(fun() ->
    +                  io:setopts([{expand_fun, fun expand_fun/1}]),
    +                  io:format(~"Starting process inspection shell~n"),
    +                  loop()
    +          end).
     
    --spec expand_fun(ReverseLine :: string()) -> {yes, string(), list(string())} |
    -          {no, nil(), nil()}.
    -expand_fun("") -> %% If line is empty, we list all available commands
    -    {yes, "", ["list", "inspect", "suspend", "resume"]};
    -expand_fun(Curr) ->
    -    expand_fun(lists:reverse(Curr), ["list", "inspect", "suspend", "resume"]).
    +-spec expand_fun(ReverseLine :: string()) -> {yes, string(), list(string())} |
    +          {no, nil(), nil()}.
    +expand_fun("") -> %% If line is empty, we list all available commands
    +    {yes, "", ["list", "inspect", "suspend", "resume"]};
    +expand_fun(Curr) ->
    +    expand_fun(lists:reverse(Curr), ["list", "inspect", "suspend", "resume"]).
     
    -expand_fun(_Curr, []) ->
    -    {no, "", []};
    -expand_fun(Curr, [Cmd | T]) ->
    -    case lists:prefix(Curr, Cmd) of
    +expand_fun(_Curr, []) ->
    +    {no, "", []};
    +expand_fun(Curr, [Cmd | T]) ->
    +    case lists:prefix(Curr, Cmd) of
             true ->
                 %% If Curr is a prefix of Cmd we subtract Curr from Cmd to get the
                 %% characters we need to complete with.
    -            {yes, lists:reverse(lists:reverse(Cmd) -- lists:reverse(Curr)), []};
    +            {yes, lists:reverse(lists:reverse(Cmd) -- lists:reverse(Curr)), []};
             false ->
    -            expand_fun(Curr, T)
    +            expand_fun(Curr, T)
         end.

    With the above code we will get expansions of our commands if we hit <TAB> in the shell. Its possible to make very complex completion algorithms, for example the Erlang shell has completions based on the function specifications of your code. It is important though that /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/c.xhtml differs (HTML document, ASCII text, with very long lines (723)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/c.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/c.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -1630,7 +1630,7 @@

    Compiles and then loads the code for a file on all nodes. Options defaults to -[]. Compilation is equivalent to:

    compile:file(File, Options ++ [report_errors, report_warnings])
    +[]. Compilation is equivalent to:

    compile:file(File, Options ++ [report_errors, report_warnings])
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/dets.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (613)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/dets.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/dets.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -1786,14 +1786,14 @@

    Returns a list of all objects with key Key stored in table Name, for -example:

    2> dets:open_file(abc, [{type, bag}]).
    -{ok,abc}
    -3> dets:insert(abc, {1,2,3}).
    +example:

    2> dets:open_file(abc, [{type, bag}]).
    +{ok,abc}
    +3> dets:insert(abc, {1,2,3}).
     ok
    -4> dets:insert(abc, {1,3,4}).
    +4> dets:insert(abc, {1,3,4}).
     ok
    -5> dets:lookup(abc, 1).
    -[{1,2,3},{1,3,4}]

    If the table type is set, the function returns either the empty list or a list +5> dets:lookup(abc, 1). +[{1,2,3},{1,3,4}]

    If the table type is set, the function returns either the empty list or a list with one object, as there cannot be more than one object with a given key. If the table type is bag or duplicate_bag, the function returns a list of arbitrary length.

    Notice that the order of objects returned is unspecified. In particular, the @@ -2650,11 +2650,11 @@ specification is specified explicitly. This is how to state match specifications that cannot easily be expressed within the syntax provided by qlc.

    The following example uses an explicit match specification to traverse the -table:

    1> dets:open_file(t, []),
    -ok = dets:insert(t, [{1,a},{2,b},{3,c},{4,d}]),
    -MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),
    -QH1 = dets:table(t, [{traverse, {select, MS}}]).

    An example with implicit match specification:

    2> QH2 = qlc:q([{Y} || {X,Y} <- dets:table(t), (X > 1) or (X < 5)]).

    The latter example is equivalent to the former, which can be verified using -function qlc:info/1:

    3> qlc:info(QH1) =:= qlc:info(QH2).
    +table:

    1> dets:open_file(t, []),
    +ok = dets:insert(t, [{1,a},{2,b},{3,c},{4,d}]),
    +MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),
    +QH1 = dets:table(t, [{traverse, {select, MS}}]).

    An example with implicit match specification:

    2> QH2 = qlc:q([{Y} || {X,Y} <- dets:table(t), (X > 1) or (X < 5)]).

    The latter example is equivalent to the former, which can be verified using +function qlc:info/1:

    3> qlc:info(QH1) =:= qlc:info(QH2).
     true

    qlc:info/1 returns information about a query handle. In this case identical information is returned for the two query handles.

    @@ -2728,7 +2728,7 @@

    Applies Fun to each object stored in table Name in some unspecified order. Different actions are taken depending on the return value of Fun. The following Fun return values are allowed:

    • continue - Continue to perform the traversal. For example, the following -function can be used to print the contents of a table:

      fun(X) -> io:format("~p~n", [X]), continue end.
    • {continue, Val} - Continue the traversal and accumulate Val. The +function can be used to print the contents of a table:

      fun(X) -> io:format("~p~n", [X]), continue end.
    • {continue, Val} - Continue the traversal and accumulate Val. The following function is supplied to collect all objects of a table in a list:

      fun(X) -> {continue, X} end.
    • {done, Value} - Terminate the traversal and return [Value | Acc].

    Any other value OtherValue returned by Fun terminates the traversal and is returned immediately.

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/dict.xhtml differs (HTML document, ASCII text, with very long lines (1050)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/dict.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/dict.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -26,13 +26,13 @@ difference is that while this module considers two keys as different if they do not match (=:=), orddict considers two keys as different if and only if they do not compare equal (==).

    Notes

    Functions append and append_list are included so that keyed values can be -stored in a list accumulator, for example:

    > D0 = dict:new(),
    -  D1 = dict:store(files, [], D0),
    -  D2 = dict:append(files, f1, D1),
    -  D3 = dict:append(files, f2, D2),
    -  D4 = dict:append(files, f3, D3),
    -  dict:fetch(files, D4).
    -[f1,f2,f3]

    This saves the trouble of first fetching a keyed value, appending a new value to +stored in a list accumulator, for example:

    > D0 = dict:new(),
    +  D1 = dict:store(files, [], D0),
    +  D2 = dict:append(files, f1, D1),
    +  D3 = dict:append(files, f2, D2),
    +  D4 = dict:append(files, f3, D3),
    +  dict:fetch(files, D4).
    +[f1,f2,f3]

    This saves the trouble of first fetching a keyed value, appending a new value to the list of stored values, and storing the result.

    Function fetch is to be used if the key is known to be in the dictionary, otherwise function find.

    See Also

    gb_trees, orddict

    @@ -771,10 +771,10 @@ the Key-Value pairs from both dictionaries are included in the new dictionary. If a key occurs in both dictionaries, Fun is called with the key and both values to return a new value. merge can be defined as follows, but is -faster:

    merge(Fun, D1, D2) ->
    -    fold(fun (K, V1, D) ->
    -                 update(K, fun (V2) -> Fun(K, V1, V2) end, V1, D)
    -         end, D2, D1).
    +faster:

    merge(Fun, D1, D2) ->
    +    fold(fun (K, V1, D) ->
    +                 update(K, fun (V2) -> Fun(K, V1, V2) end, V1, D)
    +         end, D2, D1).
    @@ -987,8 +987,8 @@

    Updates a value in a dictionary by calling Fun on the value to get a new value. If Key is not present in the dictionary, Initial is stored as the -first value. For example, append/3 can be defined as:

    append(Key, Val, D) ->
    -    update(Key, fun (Old) -> Old ++ [Val] end, [Val], D).
    +first value. For example, append/3 can be defined as:

    append(Key, Val, D) ->
    +    update(Key, fun (Old) -> Old ++ [Val] end, [Val], D).
    @@ -1019,8 +1019,8 @@

    Adds Increment to the value associated with Key and stores this value. If Key is not present in the dictionary, Increment is stored as the first -value.

    This can be defined as follows, but is faster:

    update_counter(Key, Incr, D) ->
    -    update(Key, fun (Old) -> Old + Incr end, Incr, D).
    +value.

    This can be defined as follows, but is faster:

    update_counter(Key, Incr, D) ->
    +    update(Key, fun (Old) -> Old + Incr end, Incr, D).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/epp.xhtml differs (HTML document, ASCII text, with very long lines (879)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/epp.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/epp.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -28,7 +28,7 @@ expression coding\s*[:=]\s*([-a-zA-Z0-9])+ selects the encoding. If the matching string is not a valid encoding, it is ignored. The valid encodings are Latin-1 and UTF-8, where the case of the characters can be chosen freely.

    Examples:

    %% coding: utf-8
    %% For this file we have chosen encoding = Latin-1
    %% -*- coding: latin-1 -*-

    Error Information

    ErrorInfo is the standard ErrorInfo structure that is returned from all I/O -modules. The format is as follows:

    {ErrorLine, Module, ErrorDescriptor}

    A string describing the error is obtained with the following call:

    Module:format_error(ErrorDescriptor)

    See Also

    erl_parse

    +modules. The format is as follows:

    {ErrorLine, Module, ErrorDescriptor}

    A string describing the error is obtained with the following call:

    Module:format_error(ErrorDescriptor)

    See Also

    erl_parse

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_error.xhtml differs (HTML document, ASCII text, with very long lines (1131)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_error.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_error.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -194,7 +194,7 @@

    A fun used to format function arguments for BIF and function calls. By default -the following fun will be used:

    fun(Term, I) -> io_lib:print(Term, I, 80, 30) end
    +the following fun will be used:

    fun(Term, I) -> io_lib:print(Term, I, 80, 30) end
    @@ -310,23 +310,23 @@ caused the error starting at 1.

  • general - An error that is not associated with any argument caused the error.

  • reason - If the Reason should be printed differently than the default way.

  • If the text returned includes new-lines, format_exception/4 will indent the -text correctly.

    Example:

    -module(my_error_module).
    --export([atom_to_string/1, format_error/2]).
    +text correctly.

    Example:

    -module(my_error_module).
    +-export([atom_to_string/1, format_error/2]).
     
    -atom_to_string(Arg) when is_atom(Arg) ->
    -  atom_to_list(Arg);
    -atom_to_string(Arg) ->
    -  erlang:error(badarg,[Arg],
    -               [{error_info,#{ module => ?MODULE,
    -                               cause => #{ 1 => "should be an atom" }}}]).
    -
    -format_error(Reason, [{_M,_F,_As,Info}|_]) ->
    -  ErrorInfo = proplists:get_value(error_info, Info, #{}),
    -  ErrorMap = maps:get(cause, ErrorInfo),
    -  ErrorMap#{ general => "optional general information",
    -             reason => io_lib:format("~p: ~p",[?MODULE, Reason]) }.
    1> c(my_error_module).
    -{ok,my_error_module}
    -2> my_error_module:atom_to_string(1).
    +atom_to_string(Arg) when is_atom(Arg) ->
    +  atom_to_list(Arg);
    +atom_to_string(Arg) ->
    +  erlang:error(badarg,[Arg],
    +               [{error_info,#{ module => ?MODULE,
    +                               cause => #{ 1 => "should be an atom" }}}]).
    +
    +format_error(Reason, [{_M,_F,_As,Info}|_]) ->
    +  ErrorInfo = proplists:get_value(error_info, Info, #{}),
    +  ErrorMap = maps:get(cause, ErrorInfo),
    +  ErrorMap#{ general => "optional general information",
    +             reason => io_lib:format("~p: ~p",[?MODULE, Reason]) }.
    1> c(my_error_module).
    +{ok,my_error_module}
    +2> my_error_module:atom_to_string(1).
     ** exception error: my_error_module: badarg
          in function  my_error_module:atom_to_string/1
             called as my_error_module:atom_to_string(1)
    @@ -409,18 +409,18 @@
     
     

    Format the error reason and stack back-trace caught using try ... catch in the same style as the shell formats them.

    Example:

    try
    -    do_something()
    +    do_something()
     catch
         C:R:Stk ->
    -        Message = erl_error:format_exception(C, R, Stk),
    -        io:format(LogFile, "~ts\n", [Message])
    +        Message = erl_error:format_exception(C, R, Stk),
    +        io:format(LogFile, "~ts\n", [Message])
     end

    If error_info is provided with the exception, format_exception will use that information to provide additional information about the exception.

    Example:

    try
    -  erlang:raise(badarg,[],[{error_info,#{}}])
    +  erlang:raise(badarg,[],[{error_info,#{}}])
     catch
         C:R:Stk ->
    -        Message = erl_error:format_exception(C, R, Stk),
    -        io:format(LogFile, "~ts\n", [Message])
    +        Message = erl_error:format_exception(C, R, Stk),
    +        io:format(LogFile, "~ts\n", [Message])
     end

    See erlang:error/3 for details on how to raise an exception with error_info included.

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_eval.xhtml differs (HTML document, ASCII text, with very long lines (922)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_eval.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_eval.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -29,13 +29,13 @@ LocalFunctionHandler can be used to define a function that is called when there is a call to a local function. The argument can have the following formats:

    • {value,Func} - This defines a local function handler that is called -with:

      Func(Name, Arguments)

      Name is the name of the local function (an atom) and Arguments is a list +with:

      Func(Name, Arguments)

      Name is the name of the local function (an atom) and Arguments is a list of the evaluated arguments. The function handler returns the value of the local function. In this case, the current bindings cannot be accessed. To signal an error, the function handler calls exit/1 with a -suitable exit value.

    • {eval,Func} - This defines a local function handler that is called with:

      Func(Name, Arguments, Bindings)

      Name is the name of the local function (an atom), Arguments is a list of +suitable exit value.

    • {eval,Func} - This defines a local function handler that is called with:

      Func(Name, Arguments, Bindings)

      Name is the name of the local function (an atom), Arguments is a list of the unevaluated arguments, and Bindings are the current variable bindings. -The function handler returns:

      {value,Value,NewBindings}

      Value is the value of the local function and NewBindings are the updated +The function handler returns:

      {value,Value,NewBindings}

      Value is the value of the local function and NewBindings are the updated variable bindings. In this case, the function handler must itself evaluate all the function arguments and manage the bindings. To signal an error, the function handler calls exit/1 with a suitable exit value.

    • none - There is no local function handler.

    Non-Local Function Handler

    The optional argument NonLocalFunctionHandler can be used to define a function @@ -43,7 +43,7 @@ expressions.

  • An operator Op/A is called (this is handled as a call to function erlang:Op/A).
  • Exceptions are calls to erlang:apply/2,3; neither of the function handlers are called for such calls. The argument can have the following formats:

    • {value,Func} - This defines a non-local function handler. The function -may be called with two arguments:

      Func(FuncSpec, Arguments)

      or three arguments:

      Func(Anno, FuncSpec, Arguments)

      Anno is the erl_anno:anno() of the node, FuncSpec +may be called with two arguments:

      Func(FuncSpec, Arguments)

      or three arguments:

      Func(Anno, FuncSpec, Arguments)

      Anno is the erl_anno:anno() of the node, FuncSpec is the name of the function of the form {Module,Function} or a fun, and Arguments is a list of the evaluated arguments. The function handler returns the value of the function. To signal an error, the function handler /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_lint.xhtml differs (HTML document, ASCII text, with very long lines (936)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_lint.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_lint.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -27,7 +27,7 @@ appropriate option, described below.

      The functions in this module are invoked automatically by the Erlang compiler. There is no reason to invoke these functions separately unless you have written your own Erlang compiler.

      Error Information

      ErrorInfo is the standard ErrorInfo structure that is returned from all I/O -modules. The format is as follows:

      {ErrorLine, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      See Also

      epp, erl_parse

      +modules. The format is as follows:

      {ErrorLine, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      See Also

      epp, erl_parse

      /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_parse.xhtml differs (HTML document, ASCII text, with very long lines (1076)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_parse.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_parse.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -26,7 +26,7 @@ form of either forms (that is, top-level constructs), expressions, or terms.

      The Abstract Format is described in the ERTS User's Guide. Notice that a token list must end with the dot token to be acceptable to the parse functions (see the erl_scan) module.

      Error Information

      ErrorInfo is the standard ErrorInfo structure that is returned from all I/O modules. -The format is as follows:

      {ErrorLine, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      See Also

      erl_anno, erl_scan, io, section The Abstract Format +The format is as follows:

      {ErrorLine, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      See Also

      erl_anno, erl_scan, io, section The Abstract Format in the ERTS User's Guide.

      /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_scan.xhtml differs (HTML document, ASCII text, with very long lines (882)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_scan.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_scan.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -24,7 +24,7 @@

      The Erlang token scanner.

      This module contains functions for tokenizing (scanning) characters into Erlang tokens.

      Error Information

      ErrorInfo is the standard ErrorInfo structure that is returned from all I/O -modules. The format is as follows:

      {ErrorLocation, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      Notes

      The continuation of the first call to the re-entrant input functions must be +modules. The format is as follows:

      {ErrorLocation, Module, ErrorDescriptor}

      A string describing the error is obtained with the following call:

      Module:format_error(ErrorDescriptor)

      Notes

      The continuation of the first call to the re-entrant input functions must be []. For a complete description of how the re-entrant input scheme works, see Armstrong, Virding and Williams: 'Concurrent Programming in Erlang', Chapter 13.

      See Also

      erl_anno, erl_parse, io

      /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_tar.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1320)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_tar.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/erl_tar.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -1151,14 +1151,14 @@ Notice that there is only an arity-2 read function, not an arity-1 function.

    • (position,{UserData,Position}) - Sets the position of UserData as defined for files in file:position/2

    Example:

    The following is a complete Fun parameter for reading and writing on files using the file module:

    ExampleFun =
    -   fun(write, {Fd,Data}) ->  file:write(Fd, Data);
    -      (position, {Fd,Pos}) -> file:position(Fd, Pos);
    -      (read2, {Fd,Size}) -> file:read(Fd, Size);
    -      (close, Fd) -> file:close(Fd)
    -   end

    Here Fd was specified to function init/3 as:

    {ok,Fd} = file:open(Name, ...).
    -{ok,TarDesc} = erl_tar:init(Fd, [write], ExampleFun),

    TarDesc is then used:

    erl_tar:add(TarDesc, SomeValueIwantToAdd, FileNameInTarFile),
    +   fun(write, {Fd,Data}) ->  file:write(Fd, Data);
    +      (position, {Fd,Pos}) -> file:position(Fd, Pos);
    +      (read2, {Fd,Size}) -> file:read(Fd, Size);
    +      (close, Fd) -> file:close(Fd)
    +   end

    Here Fd was specified to function init/3 as:

    {ok,Fd} = file:open(Name, ...).
    +{ok,TarDesc} = erl_tar:init(Fd, [write], ExampleFun),

    TarDesc is then used:

    erl_tar:add(TarDesc, SomeValueIwantToAdd, FileNameInTarFile),
     ...,
    -erl_tar:close(TarDesc)

    When the erl_tar core wants to, for example, write a piece of Data, it would +erl_tar:close(TarDesc)

    When the erl_tar core wants to, for example, write a piece of Data, it would call ExampleFun(write, {UserData,Data}).

    Note

    This example with the file module operations is not necessary to use directly, as that is what function open/2 in principle does.

    Warning

    The TarDescriptor term is not a file descriptor. You are advised not to rely on the specific contents of this term, as it can change in future Erlang/OTP /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/escript.xhtml differs (HTML document, ASCII text, with very long lines (1684)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/escript.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/escript.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -400,67 +400,67 @@ number of schedulers with +S3. We also extract the different sections from the newly created script:

    > Source = "%% Demo\nmain(_Args) ->\n    io:format(\"~p\",[erlang:system_info(schedulers)]).\n".
     "%% Demo\nmain(_Args) ->\n    io:format(erlang:system_info(schedulers)).\n"
    -> io:format("~s\n", [Source]).
    +> io:format("~s\n", [Source]).
     %% Demo
    -main(_Args) ->
    -    io:format(erlang:system_info(schedulers)).
    +main(_Args) ->
    +    io:format(erlang:system_info(schedulers)).
     
     ok
    -> {ok, Bin} = escript:create(binary, [shebang, comment, {emu_args, "+S3"},
    -                                      {source, list_to_binary(Source)}]).
    -{ok,<<"#!/usr/bin/env escript\n%% This is an -*- erlang -*- file\n%%!+S3"...>>}
    -> file:write_file("demo.escript", Bin).
    +> {ok, Bin} = escript:create(binary, [shebang, comment, {emu_args, "+S3"},
    +                                      {source, list_to_binary(Source)}]).
    +{ok,<<"#!/usr/bin/env escript\n%% This is an -*- erlang -*- file\n%%!+S3"...>>}
    +> file:write_file("demo.escript", Bin).
     ok
    -> os:cmd("escript demo.escript").
    +> os:cmd("escript demo.escript").
     "3"
    -> escript:extract("demo.escript", []).
    -{ok,[{shebang,default}, {comment,default}, {emu_args,"+S3"},
    -     {source,<<"%% Demo\nmain(_Args) ->\n    io:format(erlang:system_info(schedu"...>>}]}

    An escript without header can be created as follows:

    > file:write_file("demo.erl",
    -                  ["%% demo.erl\n-module(demo).\n-export([main/1]).\n\n", Source]).
    -ok
    -> {ok, _, BeamCode} = compile:file("demo.erl", [binary, debug_info]).
    -{ok,demo,
    -    <<70,79,82,49,0,0,2,208,66,69,65,77,65,116,111,109,0,0,0,
    -      79,0,0,0,9,4,100,...>>}
    -> escript:create("demo.beam", [{beam, BeamCode}]).
    -ok
    -> escript:extract("demo.beam", []).
    -{ok,[{shebang,undefined}, {comment,undefined}, {emu_args,undefined},
    -     {beam,<<70,79,82,49,0,0,3,68,66,69,65,77,65,116,
    -             111,109,0,0,0,83,0,0,0,9,...>>}]}
    -> os:cmd("escript demo.beam").
    +> escript:extract("demo.escript", []).
    +{ok,[{shebang,default}, {comment,default}, {emu_args,"+S3"},
    +     {source,<<"%% Demo\nmain(_Args) ->\n    io:format(erlang:system_info(schedu"...>>}]}

    An escript without header can be created as follows:

    > file:write_file("demo.erl",
    +                  ["%% demo.erl\n-module(demo).\n-export([main/1]).\n\n", Source]).
    +ok
    +> {ok, _, BeamCode} = compile:file("demo.erl", [binary, debug_info]).
    +{ok,demo,
    +    <<70,79,82,49,0,0,2,208,66,69,65,77,65,116,111,109,0,0,0,
    +      79,0,0,0,9,4,100,...>>}
    +> escript:create("demo.beam", [{beam, BeamCode}]).
    +ok
    +> escript:extract("demo.beam", []).
    +{ok,[{shebang,undefined}, {comment,undefined}, {emu_args,undefined},
    +     {beam,<<70,79,82,49,0,0,3,68,66,69,65,77,65,116,
    +             111,109,0,0,0,83,0,0,0,9,...>>}]}
    +> os:cmd("escript demo.beam").
     "true"

    Here we create an archive script containing both Erlang code and Beam code, then we iterate over all files in the archive and collect their contents and some -information about them:

    > {ok, SourceCode} = file:read_file("demo.erl").
    -{ok,<<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}
    -> escript:create("demo.escript",
    -                 [shebang,
    -                  {archive, [{"demo.erl", SourceCode},
    -                             {"demo.beam", BeamCode}], []}]).
    -ok
    -> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined},
    -     {archive, ArchiveBin}]} = escript:extract("demo.escript", []).
    -{ok,[{shebang,default}, {comment,undefined}, {emu_args,undefined},
    -     {{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,
    -                152,61,93,107,0,0,0,118,0,...>>}]}
    -> file:write_file("demo.zip", ArchiveBin).
    -ok
    -> zip:foldl(fun(N, I, B, A) -> [{N, I(), B()} | A] end, [], "demo.zip").
    -{ok,[{"demo.beam",
    -      {file_info,748,regular,read_write,
    -                 {{2010,3,2},{0,59,22}},
    -                 {{2010,3,2},{0,59,22}},
    -                 {{2010,3,2},{0,59,22}},
    -                 54,1,0,0,0,0,0},
    -      <<70,79,82,49,0,0,2,228,66,69,65,77,65,116,111,109,0,0,0,
    -        83,0,0,...>>},
    -     {"demo.erl",
    -      {file_info,118,regular,read_write,
    -                 {{2010,3,2},{0,59,22}},
    -                 {{2010,3,2},{0,59,22}},
    -                 {{2010,3,2},{0,59,22}},
    -                 54,1,0,0,0,0,0},
    -      <<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}]}
    +information about them:

    > {ok, SourceCode} = file:read_file("demo.erl").
    +{ok,<<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}
    +> escript:create("demo.escript",
    +                 [shebang,
    +                  {archive, [{"demo.erl", SourceCode},
    +                             {"demo.beam", BeamCode}], []}]).
    +ok
    +> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined},
    +     {archive, ArchiveBin}]} = escript:extract("demo.escript", []).
    +{ok,[{shebang,default}, {comment,undefined}, {emu_args,undefined},
    +     {{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,
    +                152,61,93,107,0,0,0,118,0,...>>}]}
    +> file:write_file("demo.zip", ArchiveBin).
    +ok
    +> zip:foldl(fun(N, I, B, A) -> [{N, I(), B()} | A] end, [], "demo.zip").
    +{ok,[{"demo.beam",
    +      {file_info,748,regular,read_write,
    +                 {{2010,3,2},{0,59,22}},
    +                 {{2010,3,2},{0,59,22}},
    +                 {{2010,3,2},{0,59,22}},
    +                 54,1,0,0,0,0,0},
    +      <<70,79,82,49,0,0,2,228,66,69,65,77,65,116,111,109,0,0,0,
    +        83,0,0,...>>},
    +     {"demo.erl",
    +      {file_info,118,regular,read_write,
    +                 {{2010,3,2},{0,59,22}},
    +                 {{2010,3,2},{0,59,22}},
    +                 {{2010,3,2},{0,59,22}},
    +                 54,1,0,0,0,0,0},
    +      <<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}]}
    @@ -493,16 +493,16 @@ extracted value is set to the atom default. If a section is missing, the extracted value is set to the atom undefined.

    Option compile_source only affects the result if the escript contains source code. In this case the Erlang code is automatically compiled and -{source, BeamCode} is returned instead of {source, SourceCode}.

    Example:

    > escript:create("demo.escript",
    -                 [shebang, {archive, [{"demo.erl", SourceCode},
    -                                      {"demo.beam", BeamCode}], []}]).
    -ok
    -> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined},
    -     {archive, ArchiveBin}]} =
    -              escript:extract("demo.escript", []).
    -{ok,[{{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,
    -                152,61,93,107,0,0,0,118,0,...>>}
    -     {emu_args,undefined}]}
    +{source, BeamCode} is returned instead of {source, SourceCode}.

    Example:

    > escript:create("demo.escript",
    +                 [shebang, {archive, [{"demo.erl", SourceCode},
    +                                      {"demo.beam", BeamCode}], []}]).
    +ok
    +> {ok, [{shebang,default}, {comment,undefined}, {emu_args,undefined},
    +     {archive, ArchiveBin}]} =
    +              escript:extract("demo.escript", []).
    +{ok,[{{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,
    +                152,61,93,107,0,0,0,118,0,...>>}
    +     {emu_args,undefined}]}
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/ets.xhtml differs (HTML document, ASCII text, with very long lines (1175)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/ets.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/ets.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -96,10 +96,10 @@ find the next key is not done with such guarantees. This is often not a problem, but may cause rare subtle "unexpected" effects if a concurrent process inserts objects during a traversal. For example, consider one process -doing

    ets:new(t, [ordered_set, named_table]),
    -ets:insert(t, {1}),
    -ets:insert(t, {2}),
    -ets:insert(t, {3}),

    A concurrent call to ets:first(t), done by another process, may then in rare +doing

    ets:new(t, [ordered_set, named_table]),
    +ets:insert(t, {1}),
    +ets:insert(t, {2}),
    +ets:insert(t, {3}),

    A concurrent call to ets:first(t), done by another process, may then in rare cases return 2 even though 2 has never existed in the table ordered as the first key. In the same way, a concurrent call to ets:next(t, 1) may return 3 even though 3 never existed in the table ordered directly after 1.

    Effects like this are improbable but possible. The probability will further be @@ -112,11 +112,11 @@ lookup without any table traversal at all. For ordered_set a partially bound key will limit the traversal to only scan a subset of the table based on term order. A partially bound key is either a list or a tuple with a prefix that is -fully bound. Example:

    1> T = ets:new(t,[ordered_set]), ets:insert(T, {"555-1234", "John Smith"}).
    +fully bound. Example:

    1> T = ets:new(t,[ordered_set]), ets:insert(T, {"555-1234", "John Smith"}).
     true
     2> %% Efficient search of all with area code 555
    -2> ets:match(T,{[$5,$5,$5,$- |'$1'],'$2'}).
    -[["1234","John Smith"]]

    Match Specifications

    Some of the functions use a match specification, match_spec. For a brief +2> ets:match(T,{[$5,$5,$5,$- |'$1'],'$2'}). +[["1234","John Smith"]]

    Match Specifications

    Some of the functions use a match specification, match_spec. For a brief explanation, see select/2. For a detailed description, see section Match Specifications in Erlang in ERTS User's Guide.

    A match specifications with excessive nesting will cause a system_limit error exception to be raised.

    @@ -1790,19 +1790,19 @@ -include_lib("stdlib/include/ms_transform.hrl"). to the source file.

    The fun is very restricted, it can take only a single parameter (the object to match): a sole variable or a tuple. It must use the is_ guard tests. Language constructs that have no representation in a match specification (if, case, -receive, and so on) are not allowed.

    The return value is the resulting match specification.

    Example:

    1> ets:fun2ms(fun({M,N}) when N > 3 -> M end).
    -[{{'$1','$2'},[{'>','$2',3}],['$1']}]

    Variables from the environment can be imported, so that the following works:

    2> X=3.
    +receive, and so on) are not allowed.

    The return value is the resulting match specification.

    Example:

    1> ets:fun2ms(fun({M,N}) when N > 3 -> M end).
    +[{{'$1','$2'},[{'>','$2',3}],['$1']}]

    Variables from the environment can be imported, so that the following works:

    2> X=3.
     3
    -3> ets:fun2ms(fun({M,N}) when N > X -> M end).
    -[{{'$1','$2'},[{'>','$2',{const,3}}],['$1']}]

    The imported variables are replaced by match specification const expressions, +3> ets:fun2ms(fun({M,N}) when N > X -> M end). +[{{'$1','$2'},[{'>','$2',{const,3}}],['$1']}]

    The imported variables are replaced by match specification const expressions, which is consistent with the static scoping for Erlang funs. However, local or global function calls cannot be in the guard or body of the fun. Calls to -built-in match specification functions is of course allowed:

    4> ets:fun2ms(fun({M,N}) when N > X, my_fun(M) -> M end).
    +built-in match specification functions is of course allowed:

    4> ets:fun2ms(fun({M,N}) when N > X, my_fun(M) -> M end).
     Error: fun containing local Erlang function calls
    -('my_fun' called in guard) cannot be translated into match_spec
    -{error,transform_error}
    -5> ets:fun2ms(fun({M,N}) when N > X, is_atom(M) -> M end).
    -[{{'$1','$2'},[{'>','$2',{const,3}},{is_atom,'$1'}],['$1']}]

    As shown by the example, the function can be called from the shell also. The fun +('my_fun' called in guard) cannot be translated into match_spec +{error,transform_error} +5> ets:fun2ms(fun({M,N}) when N > X, is_atom(M) -> M end). +[{{'$1','$2'},[{'>','$2',{const,3}},{is_atom,'$1'}],['$1']}]

    As shown by the example, the function can be called from the shell also. The fun must be literally in the call when used from the shell as well.

    Warning

    If the parse_transform is not applied to a module that calls this pseudo function, the call fails in runtime (with a badarg). The ets module exports a function with this name, but it is never to be called except when @@ -2427,12 +2427,12 @@

    Matches the objects in table Table against pattern Pattern.

    A pattern is a term that can contain:

    • Bound parts (Erlang terms)
    • '_' that matches any Erlang term
    • Pattern variables '$N', where N=0,1,...

    The function returns a list with one element for each matching object, where -each element is an ordered list of pattern variable bindings, for example:

    6> ets:match(T, '$1'). % Matches every object in table
    -[[{rufsen,dog,7}],[{brunte,horse,5}],[{ludde,dog,5}]]
    -7> ets:match(T, {'_',dog,'$1'}).
    -[[7],[5]]
    -8> ets:match(T, {'_',cow,'$1'}).
    -[]

    If the key is specified in the pattern, the match is very efficient. If the key +each element is an ordered list of pattern variable bindings, for example:

    6> ets:match(T, '$1'). % Matches every object in table
    +[[{rufsen,dog,7}],[{brunte,horse,5}],[{ludde,dog,5}]]
    +7> ets:match(T, {'_',dog,'$1'}).
    +[[7],[5]]
    +8> ets:match(T, {'_',cow,'$1'}).
    +[]

    If the key is specified in the pattern, the match is very efficient. If the key is not specified, that is, if it is a variable or an underscore, the entire table must be searched. The search time can be substantial if the table is very large.

    For tables of type ordered_set, the result is in the same order as in a @@ -2684,10 +2684,10 @@ execution time):

    Table = ets:new...
     MatchSpec = ...
     % The following call...
    -ets:match_spec_run(ets:tab2list(Table),
    -                   ets:match_spec_compile(MatchSpec)),
    +ets:match_spec_run(ets:tab2list(Table),
    +                   ets:match_spec_compile(MatchSpec)),
     % ...gives the same result as the more common (and more efficient)
    -ets:select(Table, MatchSpec),

    Note

    This function has limited use in normal code. It is used by the dets +ets:select(Table, MatchSpec),

    Note

    This function has limited use in normal code. It is used by the dets module to perform the dets:select/1 operations and by Mnesia during transactions.

    @@ -3055,19 +3055,19 @@ format. Given that the original match specification is kept intact, the continuation can be restored, meaning it can once again be used in subsequent select/1 calls even though it has been stored on disk or on -another node.

    Examples:

    The following sequence of calls may fail:

    T=ets:new(x,[]),
    +another node.

    Examples:

    The following sequence of calls may fail:

    T=ets:new(x,[]),
     ...
    -MS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end),
    -{_,C} = ets:select(T, MS, 10),
    -MaybeBroken = binary_to_term(term_to_binary(C)),
    -ets:select(MaybeBroken).

    The following sequence works, as the call to +MS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end), +{_,C} = ets:select(T, MS, 10), +MaybeBroken = binary_to_term(term_to_binary(C)), +ets:select(MaybeBroken).

    The following sequence works, as the call to repair_continuation/2 reestablishes the -MaybeBroken continuation.

    T=ets:new(x,[]),
    +MaybeBroken continuation.

    T=ets:new(x,[]),
     ...
    -MS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end),
    -{_,C} = ets:select(T,MS,10),
    -MaybeBroken = binary_to_term(term_to_binary(C)),
    -ets:select(ets:repair_continuation(MaybeBroken,MS)).

    Note

    This function is rarely needed in application code. It is used by Mnesia to +MS = ets:fun2ms(fun({N,_}=A) when (N rem 10) =:= 0 -> A end), +{_,C} = ets:select(T,MS,10), +MaybeBroken = binary_to_term(term_to_binary(C)), +ets:select(ets:repair_continuation(MaybeBroken,MS)).

    Note

    This function is rarely needed in application code. It is used by Mnesia to provide distributed select/3 and select/1 sequences. A normal application would either use Mnesia or keep the continuation from being converted to external format.

    The actual behavior of compiled match specifications when recreated from @@ -3112,21 +3112,21 @@ to succeed even if keys are removed during the traversal. The keys for objects inserted or deleted during a traversal may or may not be returned by next/2 depending on the ordering of keys within the table and if -the key exists at the time next/2 is called.

    Example:

    clean_all_with_value(Table,X) ->
    -    safe_fixtable(Table,true),
    -    clean_all_with_value(Table,X,ets:first(Table)),
    -    safe_fixtable(Table,false).
    +the key exists at the time next/2 is called.

    Example:

    clean_all_with_value(Table,X) ->
    +    safe_fixtable(Table,true),
    +    clean_all_with_value(Table,X,ets:first(Table)),
    +    safe_fixtable(Table,false).
     
    -clean_all_with_value(Table,X,'$end_of_table') ->
    +clean_all_with_value(Table,X,'$end_of_table') ->
         true;
    -clean_all_with_value(Table,X,Key) ->
    -    case ets:lookup(Table,Key) of
    -        [{Key,X}] ->
    -            ets:delete(Table,Key);
    +clean_all_with_value(Table,X,Key) ->
    +    case ets:lookup(Table,Key) of
    +        [{Key,X}] ->
    +            ets:delete(Table,Key);
             _ ->
                 true
         end,
    -    clean_all_with_value(Table,X,ets:next(Table,Key)).

    Notice that deleted objects are not freed from a fixed table until it has been + clean_all_with_value(Table,X,ets:next(Table,Key)).

    Notice that deleted objects are not freed from a fixed table until it has been released. If a process fixes a table but never releases it, the memory used by the deleted objects is never freed. The performance of operations on the table also degrades significantly.

    To retrieve information about which processes have fixed which tables, use @@ -3210,11 +3210,11 @@ object.

    The return value is constructed using the "match variables" bound in MatchHead or using the special match variables '$_' (the whole matching object) and '$$' (all match variables in a list), so that the following -match/2 expression:

    ets:match(Table,{'$1','$2','$3'})

    is exactly equivalent to:

    ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])

    And that the following match_object/2 call:

    ets:match_object(Table,{'$1','$2','$1'})

    is exactly equivalent to

    ets:select(Table,[{{'$1','$2','$1'},[],['$_']}])

    Composite terms can be constructed in the Result part either by simply writing -a list, so that the following code:

    ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])

    gives the same output as:

    ets:select(Table,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])

    That is, all the bound variables in the match head as a list. If tuples are to +match/2 expression:

    ets:match(Table,{'$1','$2','$3'})

    is exactly equivalent to:

    ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])

    And that the following match_object/2 call:

    ets:match_object(Table,{'$1','$2','$1'})

    is exactly equivalent to

    ets:select(Table,[{{'$1','$2','$1'},[],['$_']}])

    Composite terms can be constructed in the Result part either by simply writing +a list, so that the following code:

    ets:select(Table,[{{'$1','$2','$3'},[],['$$']}])

    gives the same output as:

    ets:select(Table,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])

    That is, all the bound variables in the match head as a list. If tuples are to be constructed, one has to write a tuple of arity 1 where the single element in the tuple is the tuple one wants to construct (as an ordinary tuple can be -mistaken for a Guard).

    Therefore the following call:

    ets:select(Table,[{{'$1','$2','$1'},[],['$_']}])

    gives the same output as:

    ets:select(Table,[{{'$1','$2','$1'},[],[{{'$1','$2','$3'}}]}])

    This syntax is equivalent to the syntax used in the trace patterns (see the +mistaken for a Guard).

    Therefore the following call:

    ets:select(Table,[{{'$1','$2','$1'},[],['$_']}])

    gives the same output as:

    ets:select(Table,[{{'$1','$2','$1'},[],[{{'$1','$2','$3'}}]}])

    This syntax is equivalent to the syntax used in the trace patterns (see the dbg) module in Runtime_Tools.

    The Guards are constructed as tuples, where the first element is the test name and the remaining elements are the test parameters. To check for a specific type (say a list) of the element bound to the match variable '$1', one would write @@ -3223,7 +3223,7 @@ present in Erlang can be used, but only the new versions prefixed is_ are allowed (is_float, is_atom, and so on).

    The Guard section can also contain logic and arithmetic operations, which are written with the same syntax as the guard tests (prefix notation), so that the -following guard test written in Erlang:

    is_integer(X), is_integer(Y), X + Y < 4711

    is expressed as follows (X replaced with '$1' and Y with '$2'):

    [{is_integer, '$1'}, {is_integer, '$2'}, {'<', {'+', '$1', '$2'}, 4711}]

    For tables of type ordered_set, objects are visited in the same order as in a +following guard test written in Erlang:

    is_integer(X), is_integer(Y), X + Y < 4711

    is expressed as follows (X replaced with '$1' and Y with '$2'):

    [{is_integer, '$1'}, {is_integer, '$2'}, {'<', {'+', '$1', '$2'}, 4711}]

    For tables of type ordered_set, objects are visited in the same order as in a first/next traversal. This means that the match specification is executed against objects with keys in the first/next order and the corresponding result list is in the order of that execution.

    @@ -3375,16 +3375,16 @@ object. If not, select_replace will fail with badarg without updating any objects.

    For the moment, due to performance and semantic constraints, tables of type bag are not yet supported.

    The function returns the total number of replaced objects.

    Example

    For all 2-tuples with a list in second position, add atom 'marker' first in -the list:

    1> T = ets:new(x,[]), ets:insert(T, {key, [1, 2, 3]}).
    +the list:

    1> T = ets:new(x,[]), ets:insert(T, {key, [1, 2, 3]}).
     true
    -2> MS = ets:fun2ms(fun({K, L}) when is_list(L) -> {K, [marker | L]} end).
    -[{{'$1','$2'},[{is_list,'$2'}],[{{'$1',[marker|'$2']}}]}]
    -3> ets:select_replace(T, MS).
    +2> MS = ets:fun2ms(fun({K, L}) when is_list(L) -> {K, [marker | L]} end).
    +[{{'$1','$2'},[{is_list,'$2'}],[{{'$1',[marker|'$2']}}]}]
    +3> ets:select_replace(T, MS).
     1
    -4> ets:tab2list(T).
    -[{key,[marker,1,2,3]}]

    A generic single object compare-and-swap operation:

    [Old] = ets:lookup(T, Key),
    -New = update_object(Old),
    -Success = (1 =:= ets:select_replace(T, [{Old, [], [{const, New}]}])),
    +4>
    ets:tab2list(T). +[{key,[marker,1,2,3]}]

    A generic single object compare-and-swap operation:

    [Old] = ets:lookup(T, Key),
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/filelib.xhtml differs (HTML document, ASCII text, with very long lines (915))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/filelib.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/filelib.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -908,15 +908,15 @@
     
     

    Sanitizes the relative path by eliminating ".." and "." components to protect against directory traversal attacks.

    Either returns the sanitized path name, or the atom unsafe if the path is unsafe. -The path is considered unsafe in the following circumstances:

    • The path is not relative.
    • A ".." component would climb up above the root of the relative path.
    • A symbolic link in the path points above the root of the relative path.

    Examples:

    1> {ok, Cwd} = file:get_cwd().
    +The path is considered unsafe in the following circumstances:

    • The path is not relative.
    • A ".." component would climb up above the root of the relative path.
    • A symbolic link in the path points above the root of the relative path.

    Examples:

    1> {ok, Cwd} = file:get_cwd().
     ...
    -2> filelib:safe_relative_path("dir/sub_dir/..", Cwd).
    +2> filelib:safe_relative_path("dir/sub_dir/..", Cwd).
     "dir"
    -3> filelib:safe_relative_path("dir/..", Cwd).
    -[]
    -4> filelib:safe_relative_path("dir/../..", Cwd).
    +3> filelib:safe_relative_path("dir/..", Cwd).
    +[]
    +4> filelib:safe_relative_path("dir/../..", Cwd).
     unsafe
    -5> filelib:safe_relative_path("/abs/path", Cwd).
    +5> filelib:safe_relative_path("/abs/path", Cwd).
     unsafe
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/filename.xhtml differs (HTML document, ASCII text, with very long lines (1045)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/filename.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/filename.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -404,20 +404,20 @@

    Converts a relative Filename and returns an absolute name. No attempt is made to create the shortest absolute name, as this can give incorrect results on file -systems that allow links.

    Unix examples:

    1> pwd().
    +systems that allow links.

    Unix examples:

    1> pwd().
     "/usr/local"
    -2> filename:absname("foo").
    +2> filename:absname("foo").
     "/usr/local/foo"
    -3> filename:absname("../x").
    +3> filename:absname("../x").
     "/usr/local/../x"
    -4> filename:absname("/").
    -"/"

    Windows examples:

    1> pwd().
    +4> filename:absname("/").
    +"/"

    Windows examples:

    1> pwd().
     "D:/usr/local"
    -2> filename:absname("foo").
    +2> filename:absname("foo").
     "D:/usr/local/foo"
    -3> filename:absname("../x").
    +3> filename:absname("../x").
     "D:/usr/local/../x"
    -4> filename:absname("/").
    +4> filename:absname("/").
     "D:/"
    @@ -556,58 +556,58 @@

    Returns a suitable path, or paths, for a given type.

    If os is not set in Opts the function will default to the native option, that is 'linux', 'darwin' or 'windows', as understood by os:type/0. Anything not recognized as 'darwin' or 'windows' is interpreted as 'linux'.

    The options 'author' and 'version' are only used with 'windows' option -mode.

    • user_cache

      The path location is intended for transient data files on a local machine.

      On Linux: Respects the os environment variable XDG_CACHE_HOME.

      1> filename:basedir(user_cache, "my_application", #{os=>linux}).
      -"/home/otptest/.cache/my_application"

      On Darwin:

      1> filename:basedir(user_cache, "my_application", #{os=>darwin}).
      -"/home/otptest/Library/Caches/my_application"

      On Windows:

      1> filename:basedir(user_cache, "My App").
      +mode.

      • user_cache

        The path location is intended for transient data files on a local machine.

        On Linux: Respects the os environment variable XDG_CACHE_HOME.

        1> filename:basedir(user_cache, "my_application", #{os=>linux}).
        +"/home/otptest/.cache/my_application"

        On Darwin:

        1> filename:basedir(user_cache, "my_application", #{os=>darwin}).
        +"/home/otptest/Library/Caches/my_application"

        On Windows:

        1> filename:basedir(user_cache, "My App").
         "c:/Users/otptest/AppData/Local/My App/Cache"
        -2> filename:basedir(user_cache, "My App").
        +2> filename:basedir(user_cache, "My App").
         "c:/Users/otptest/AppData/Local/My App/Cache"
        -3> filename:basedir(user_cache, "My App", #{author=>"Erlang"}).
        +3> filename:basedir(user_cache, "My App", #{author=>"Erlang"}).
         "c:/Users/otptest/AppData/Local/Erlang/My App/Cache"
        -4> filename:basedir(user_cache, "My App", #{version=>"1.2"}).
        +4> filename:basedir(user_cache, "My App", #{version=>"1.2"}).
         "c:/Users/otptest/AppData/Local/My App/1.2/Cache"
        -5> filename:basedir(user_cache, "My App", #{author=>"Erlang",version=>"1.2"}).
        -"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Cache"
      • user_config

        The path location is intended for persistent configuration files.

        On Linux: Respects the os environment variable XDG_CONFIG_HOME.

        2> filename:basedir(user_config, "my_application", #{os=>linux}).
        -"/home/otptest/.config/my_application"

        On Darwin:

        2> filename:basedir(user_config, "my_application", #{os=>darwin}).
        -"/home/otptest/Library/Application Support/my_application"

        On Windows:

        1> filename:basedir(user_config, "My App").
        +5> filename:basedir(user_cache, "My App", #{author=>"Erlang",version=>"1.2"}).
        +"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Cache"
      • user_config

        The path location is intended for persistent configuration files.

        On Linux: Respects the os environment variable XDG_CONFIG_HOME.

        2> filename:basedir(user_config, "my_application", #{os=>linux}).
        +"/home/otptest/.config/my_application"

        On Darwin:

        2> filename:basedir(user_config, "my_application", #{os=>darwin}).
        +"/home/otptest/Library/Application Support/my_application"

        On Windows:

        1> filename:basedir(user_config, "My App").
         "c:/Users/otptest/AppData/Roaming/My App"
        -2> filename:basedir(user_config, "My App", #{author=>"Erlang", version=>"1.2"}).
        -"c:/Users/otptest/AppData/Roaming/Erlang/My App/1.2"
      • user_data

        The path location is intended for persistent data files.

        On Linux: Respects the os environment variable XDG_DATA_HOME.

        3> filename:basedir(user_data, "my_application", #{os=>linux}).
        -"/home/otptest/.local/my_application"

        On Darwin:

        3> filename:basedir(user_data, "my_application", #{os=>darwin}).
        -"/home/otptest/Library/Application Support/my_application"

        On Windows:

        8> filename:basedir(user_data, "My App").
        +2> filename:basedir(user_config, "My App", #{author=>"Erlang", version=>"1.2"}).
        +"c:/Users/otptest/AppData/Roaming/Erlang/My App/1.2"
      • user_data

        The path location is intended for persistent data files.

        On Linux: Respects the os environment variable XDG_DATA_HOME.

        3> filename:basedir(user_data, "my_application", #{os=>linux}).
        +"/home/otptest/.local/my_application"

        On Darwin:

        3> filename:basedir(user_data, "my_application", #{os=>darwin}).
        +"/home/otptest/Library/Application Support/my_application"

        On Windows:

        8> filename:basedir(user_data, "My App").
         "c:/Users/otptest/AppData/Local/My App"
        -9> filename:basedir(user_data, "My App",#{author=>"Erlang",version=>"1.2"}).
        -"c:/Users/otptest/AppData/Local/Erlang/My App/1.2"
      • user_log

        The path location is intended for transient log files on a local machine.

        On Linux: Respects the os environment variable XDG_CACHE_HOME.

        4> filename:basedir(user_log, "my_application", #{os=>linux}).
        -"/home/otptest/.cache/my_application/log"

        On Darwin:

        4> filename:basedir(user_log, "my_application", #{os=>darwin}).
        -"/home/otptest/Library/Logs/my_application"

        On Windows:

        12> filename:basedir(user_log, "My App").
        +9> filename:basedir(user_data, "My App",#{author=>"Erlang",version=>"1.2"}).
        +"c:/Users/otptest/AppData/Local/Erlang/My App/1.2"
      • user_log

        The path location is intended for transient log files on a local machine.

        On Linux: Respects the os environment variable XDG_CACHE_HOME.

        4> filename:basedir(user_log, "my_application", #{os=>linux}).
        +"/home/otptest/.cache/my_application/log"

        On Darwin:

        4> filename:basedir(user_log, "my_application", #{os=>darwin}).
        +"/home/otptest/Library/Logs/my_application"

        On Windows:

        12> filename:basedir(user_log, "My App").
         "c:/Users/otptest/AppData/Local/My App/Logs"
        -13> filename:basedir(user_log, "My App",#{author=>"Erlang",version=>"1.2"}).
        -"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Logs"
      • site_config

        On Linux: Respects the os environment variable XDG_CONFIG_DIRS.

        5> filename:basedir(site_config, "my_application", #{os=>linux}).
        -["/usr/local/share/my_application",
        - "/usr/share/my_application"]
        -6> os:getenv("XDG_CONFIG_DIRS").
        +13> filename:basedir(user_log, "My App",#{author=>"Erlang",version=>"1.2"}).
        +"c:/Users/otptest/AppData/Local/Erlang/My App/1.2/Logs"
      • site_config

        On Linux: Respects the os environment variable XDG_CONFIG_DIRS.

        5> filename:basedir(site_config, "my_application", #{os=>linux}).
        +["/usr/local/share/my_application",
        + "/usr/share/my_application"]
        +6> os:getenv("XDG_CONFIG_DIRS").
         "/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg"
        -7> filename:basedir(site_config, "my_application", #{os=>linux}).
        -["/etc/xdg/xdg-ubuntu/my_application",
        +7> filename:basedir(site_config, "my_application", #{os=>linux}).
        +["/etc/xdg/xdg-ubuntu/my_application",
          "/usr/share/upstart/xdg/my_application",
        - "/etc/xdg/my_application"]
        -8> os:unsetenv("XDG_CONFIG_DIRS").
        + "/etc/xdg/my_application"]
        +8> os:unsetenv("XDG_CONFIG_DIRS").
         true
        -9> filename:basedir(site_config, "my_application", #{os=>linux}).
        -["/etc/xdg/my_application"]

        On Darwin:

        5> filename:basedir(site_config, "my_application", #{os=>darwin}).
        -["/Library/Application Support/my_application"]
      • site_data

        On Linux: Respects the os environment variable XDG_DATA_DIRS.

        10> os:getenv("XDG_DATA_DIRS").
        +9> filename:basedir(site_config, "my_application", #{os=>linux}).
        +["/etc/xdg/my_application"]

        On Darwin:

        5> filename:basedir(site_config, "my_application", #{os=>darwin}).
        +["/Library/Application Support/my_application"]
      • site_data

        On Linux: Respects the os environment variable XDG_DATA_DIRS.

        10> os:getenv("XDG_DATA_DIRS").
         "/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/"
        -11> filename:basedir(site_data, "my_application", #{os=>linux}).
        -["/usr/share/ubuntu/my_application",
        +11> filename:basedir(site_data, "my_application", #{os=>linux}).
        +["/usr/share/ubuntu/my_application",
          "/usr/share/gnome/my_application",
          "/usr/local/share/my_application",
        - "/usr/share/my_application"]
        -12> os:unsetenv("XDG_DATA_DIRS").
        + "/usr/share/my_application"]
        +12> os:unsetenv("XDG_DATA_DIRS").
         true
        -13> filename:basedir(site_data, "my_application", #{os=>linux}).
        -["/usr/local/share/my_application",
        - "/usr/share/my_application"]

        On Darwin:

        5> filename:basedir(site_data, "my_application", #{os=>darwin}).
        -["/Library/Application Support/my_application"]
      +13>
      filename:basedir(site_data, "my_application", #{os=>linux}). +["/usr/local/share/my_application", + "/usr/share/my_application"]

      On Darwin:

      5> filename:basedir(site_data, "my_application", #{os=>darwin}).
      +["/Library/Application Support/my_application"]
    @@ -636,12 +636,12 @@

    Returns the last component of Filename, or Filename itself if it does not -contain any directory separators.

    Examples:

    5> filename:basename("foo").
    +contain any directory separators.

    Examples:

    5> filename:basename("foo").
     "foo"
    -6> filename:basename("/usr/foo").
    +6> filename:basename("/usr/foo").
     "foo"
    -7> filename:basename("/").
    -[]
    +7>
    filename:basename("/"). +[]
    @@ -672,15 +672,15 @@

    Returns the last component of Filename with extension Ext stripped.

    This function is to be used to remove a (possible) specific extension. To remove an existing extension when you are unsure which one it is, use -rootname(basename(Filename)).

    Examples:

    8> filename:basename("~/src/kalle.erl", ".erl").
    +rootname(basename(Filename)).

    Examples:

    8> filename:basename("~/src/kalle.erl", ".erl").
     "kalle"
    -9> filename:basename("~/src/kalle.beam", ".erl").
    +9> filename:basename("~/src/kalle.beam", ".erl").
     "kalle.beam"
    -10> filename:basename("~/src/kalle.old.erl", ".erl").
    +10> filename:basename("~/src/kalle.old.erl", ".erl").
     "kalle.old"
    -11> filename:rootname(filename:basename("~/src/kalle.erl")).
    +11> filename:rootname(filename:basename("~/src/kalle.erl")).
     "kalle"
    -12> filename:rootname(filename:basename("~/src/kalle.beam")).
    +12> filename:rootname(filename:basename("~/src/kalle.beam")).
     "kalle"
    @@ -709,10 +709,10 @@ -

    Returns the directory part of Filename.

    Examples:

    13> filename:dirname("/usr/src/kalle.erl").
    +

    Returns the directory part of Filename.

    Examples:

    13> filename:dirname("/usr/src/kalle.erl").
     "/usr/src"
    -14> filename:dirname("kalle.erl").
    -"."
    5> filename:dirname("\\usr\\src/kalle.erl"). % Windows
    +14> filename:dirname("kalle.erl").
    +"."
    5> filename:dirname("\\usr\\src/kalle.erl"). % Windows
     "/usr/src"
    @@ -742,10 +742,10 @@

    Returns the file extension of Filename, including the period. Returns an empty -string if no extension exists.

    Examples:

    15> filename:extension("foo.erl").
    +string if no extension exists.

    Examples:

    15> filename:extension("foo.erl").
     ".erl"
    -16> filename:extension("beam.src/kalle").
    -[]
    +16>
    filename:extension("beam.src/kalle"). +[]
    @@ -805,10 +805,10 @@

    Joins a list of filename Components with directory separators. If one of the elements of Components includes an absolute path, such as "/xxx", the preceding elements, if any, are removed from the result.

    The result is "normalized":

    • Redundant directory separators are removed.
    • In Windows, all directory separators are forward slashes and the drive letter -is in lower case.

    Examples:

    17> filename:join(["/usr", "local", "bin"]).
    +is in lower case.

    Examples:

    17> filename:join(["/usr", "local", "bin"]).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/file_sorter.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1046))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/file_sorter.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/file_sorter.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -89,35 +89,35 @@
     argument {value, Value}. This makes it easy to initiate the sequence of output
     functions with a value calculated by the input functions.

    As an example, consider sorting the terms on a disk log file. A function that reads chunks from the disk log and returns a list of binaries is used as input. -The results are collected in a list of terms.

    sort(Log) ->
    -    {ok, _} = disk_log:open([{name,Log}, {mode,read_only}]),
    -    Input = input(Log, start),
    -    Output = output([]),
    -    Reply = file_sorter:sort(Input, Output, {format,term}),
    -    ok = disk_log:close(Log),
    +The results are collected in a list of terms.

    sort(Log) ->
    +    {ok, _} = disk_log:open([{name,Log}, {mode,read_only}]),
    +    Input = input(Log, start),
    +    Output = output([]),
    +    Reply = file_sorter:sort(Input, Output, {format,term}),
    +    ok = disk_log:close(Log),
         Reply.
     
    -input(Log, Cont) ->
    -    fun(close) ->
    +input(Log, Cont) ->
    +    fun(close) ->
                 ok;
    -       (read) ->
    -            case disk_log:chunk(Log, Cont) of
    -                {error, Reason} ->
    -                    {error, Reason};
    -                {Cont2, Terms} ->
    -                    {Terms, input(Log, Cont2)};
    -                {Cont2, Terms, _Badbytes} ->
    -                    {Terms, input(Log, Cont2)};
    +       (read) ->
    +            case disk_log:chunk(Log, Cont) of
    +                {error, Reason} ->
    +                    {error, Reason};
    +                {Cont2, Terms} ->
    +                    {Terms, input(Log, Cont2)};
    +                {Cont2, Terms, _Badbytes} ->
    +                    {Terms, input(Log, Cont2)};
                     eof ->
                         end_of_input
                 end
         end.
     
    -output(L) ->
    -    fun(close) ->
    -            lists:append(lists:reverse(L));
    -       (Terms) ->
    -            output([Terms | L])
    +output(L) ->
    +    fun(close) ->
    +            lists:append(lists:reverse(L));
    +       (Terms) ->
    +            output([Terms | L])
         end.

    For more examples of functions as input and output, see the end of the file_sorter module; the term format is implemented with functions.

    The possible values of Reason returned when an error occurs are:

    • bad_object, {bad_object, FileName} - Applying the format function failed for some binary, or the key(s) could not be extracted from some term.
    • {bad_term, FileName} - io:read/2 failed to read some term.
    • {file_error, FileName, file:posix()} - For an explanation of /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gb_sets.xhtml differs (HTML document, ASCII text, with very long lines (1514)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gb_sets.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gb_sets.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -712,14 +712,14 @@ -

      Returns a new set formed from Set1 with Element inserted.

      If Element is already an element in Set1, nothing is changed.

      Examples

      1> S0 = gb_sets:new().
      -2> S1 = gb_sets:add_element(7, S0).
      -3> gb_sets:to_list(S1).
      -[7]
      -4> S2 = gb_sets:add_element(42, S1).
      -5> S2 = gb_sets:add_element(42, S1).
      -6> gb_sets:to_list(S2).
      -[7,42]
      +

      Returns a new set formed from Set1 with Element inserted.

      If Element is already an element in Set1, nothing is changed.

      Examples

      1> S0 = gb_sets:new().
      +2> S1 = gb_sets:add_element(7, S0).
      +3> gb_sets:to_list(S1).
      +[7]
      +4> S2 = gb_sets:add_element(42, S1).
      +5> S2 = gb_sets:add_element(42, S1).
      +6> gb_sets:to_list(S2).
      +[7,42]
    @@ -750,12 +750,12 @@

    Rebalances the tree representation of Set1.

    This is rarely necessary, but can be motivated when a large number of elements have been deleted from the tree without further insertions. Forcing rebalancing can minimize lookup times, as deletion -does not rebalance the tree.

    Examples

    1> S0 = gb_sets:from_ordset(lists:seq(1, 100)).
    -2> Delete = fun(E, Set) -> gb_sets:delete(E, Set) end.
    -3> S1 = lists:foldl(Delete, S0, lists:seq(1, 50)).
    -4> gb_sets:size(S1).
    +does not rebalance the tree.

    Examples

    1> S0 = gb_sets:from_ordset(lists:seq(1, 100)).
    +2> Delete = fun(E, Set) -> gb_sets:delete(E, Set) end.
    +3> S1 = lists:foldl(Delete, S0, lists:seq(1, 50)).
    +4> gb_sets:size(S1).
     50
    -5> S2 = gb_sets:balance(S1).
    +5>
    S2 = gb_sets:balance(S1).
    @@ -813,9 +813,9 @@

    Returns a new set formed from Set1 with Element removed, assuming Element is present in Set1.

    Use delete_any/2 when deleting from a set where Element is potentially -missing.

    Examples

    1> S = gb_sets:from_list([a,b]).
    -2> gb_sets:to_list(gb_sets:delete(b, S)).
    -[a]
    +missing.

    Examples

    1> S = gb_sets:from_list([a,b]).
    +2> gb_sets:to_list(gb_sets:delete(b, S)).
    +[a]
    @@ -843,10 +843,10 @@ -

    Returns a new set formed from Set1 with Element removed.

    If Element is not an element in Set1, nothing is changed.

    Examples

    1> S = gb_sets:from_list([a,b]).
    -2> gb_sets:to_list(gb_sets:delete_any(b, S)).
    -[a]
    -3> S = gb_sets:delete_any(x, S).
    +

    Returns a new set formed from Set1 with Element removed.

    If Element is not an element in Set1, nothing is changed.

    Examples

    1> S = gb_sets:from_list([a,b]).
    +2> gb_sets:to_list(gb_sets:delete_any(b, S)).
    +[a]
    +3> S = gb_sets:delete_any(x, S).
    @@ -903,8 +903,8 @@ -

    Returns a new empty set.

    Examples

    1> gb_sets:to_list(gb_sets:empty()).
    -[]
    +

    Returns a new empty set.

    Examples

    1> gb_sets:to_list(gb_sets:empty()).
    +[]
    @@ -933,11 +933,11 @@ -

    Filters elements in Set1 using predicate function Pred.

    Examples

    1> S = gb_sets:from_list([1,2,3,4,5,6,7]).
    -2> IsEven = fun(N) -> N rem 2 =:= 0 end.
    -3> Filtered = gb_sets:filter(IsEven, S).
    -4> gb_sets:to_list(Filtered).
    -[2,4,6]
    +

    Filters elements in Set1 using predicate function Pred.

    Examples

    1> S = gb_sets:from_list([1,2,3,4,5,6,7]).
    +2> IsEven = fun(N) -> N rem 2 =:= 0 end.
    +3> Filtered = gb_sets:filter(IsEven, S).
    +4> gb_sets:to_list(Filtered).
    +[2,4,6]
    @@ -974,17 +974,17 @@

    Calls Fun(Elem) for each Elem of Set1 to update or remove elements from Set1.

    Fun/1 must return either a Boolean or a tuple {true, Value}. The function returns the set of elements for which Fun returns a new -value, with true being equivalent to {true, Elem}.

    gb_sets:filtermap/2 behaves as if it were defined as follows:

    filtermap(Fun, Set1) ->
    -    gb_sets:from_list(lists:filtermap(Fun, Set1)).

    Examples

    1> S = gb_sets:from_list([2,4,5,6,8,9])
    -2> F = fun(X) ->
    +value, with true being equivalent to {true, Elem}.

    gb_sets:filtermap/2 behaves as if it were defined as follows:

    filtermap(Fun, Set1) ->
    +    gb_sets:from_list(lists:filtermap(Fun, Set1)).

    Examples

    1> S = gb_sets:from_list([2,4,5,6,8,9])
    +2> F = fun(X) ->
                case X rem 2 of
    -               0 -> {true, X div 2};
    +               0 -> {true, X div 2};
                    1 -> false
                end
             end.
    -3> Set = gb_sets:filtermap(F, S).
    -4> gb_sets:to_list(Set).
    -[1,2,3,4]
    +3>
    Set = gb_sets:filtermap(F, S). +4> gb_sets:to_list(Set). +[1,2,3,4]
    @@ -1020,9 +1020,9 @@

    Folds Function over every element in Set and returns the final value of -the accumulator.

    Examples

    1> S = gb_sets:from_list([1,2,3,4]).
    +the accumulator.

    Examples

    1> S = gb_sets:from_list([1,2,3,4]).
     2> Plus = fun erlang:'+'/2.
    -3> gb_sets:fold(Plus, 0, S).
    +3> gb_sets:fold(Plus, 0, S).
     10
    @@ -1052,9 +1052,9 @@

    Returns a set of the elements in List, where List can be unordered and -contain duplicates.

    Examples

    1> Unordered = [x,y,a,x,y,b,b,z]
    -2> gb_sets:to_list(gb_sets:from_list(Unordered)).
    -[a,b,x,y,z]
    +contain duplicates.

    Examples

    1> Unordered = [x,y,a,x,y,b,b,z]
    +2> gb_sets:to_list(gb_sets:from_list(Unordered)).
    +[a,b,x,y,z]
    @@ -1083,9 +1083,9 @@

    Turns an ordered list without duplicates List into a set.

    See from_list/1 for a function that accepts unordered lists with -duplicates.

    Examples

    1> Ordset = [1,2,3].
    -2> gb_sets:to_list(gb_sets:from_ordset(Ordset)).
    -[1,2,3]
    +duplicates.

    Examples

    1> Ordset = [1,2,3].
    +2> gb_sets:to_list(gb_sets:from_ordset(Ordset)).
    +[1,2,3]
    @@ -1115,13 +1115,13 @@

    Returns a new set formed from Set1 with Element inserted, assuming Element is not already present.

    Use add/2 for inserting into a set where Element is potentially -already present.

    Examples

    1> S0 = gb_sets:new().
    -2> S1 = gb_sets:insert(7, S0).
    -3> gb_sets:to_list(S1).
    -[7]
    -4> S2 = gb_sets:insert(42, S1).
    -5> gb_sets:to_list(S2).
    -[7,42]
    +already present.

    Examples

    1> S0 = gb_sets:new().
    +2> S1 = gb_sets:insert(7, S0).
    +3> gb_sets:to_list(S1).
    +[7]
    +4> S2 = gb_sets:insert(42, S1).
    +5> gb_sets:to_list(S2).
    +[7,42]
    @@ -1150,15 +1150,15 @@

    Returns the intersection of the non-empty list of sets.

    The intersection of multiple sets is a new set that contains only the -elements that are present in all sets.

    Examples

    1> S0 = gb_sets:from_list([a,b,c,d]).
    -2> S1 = gb_sets:from_list([d,e,f]).
    -3> S2 = gb_sets:from_list([q,r])
    -4> Sets = [S0, S1, S2].
    -5> gb_sets:to_list(gb_sets:intersection([S0, S1, S2])).
    -[]
    -6> gb_sets:to_list(gb_sets:intersection([S0, S1])).
    -[d]
    -7> gb_sets:intersection([]).
    +elements that are present in all sets.

    Examples

    1> S0 = gb_sets:from_list([a,b,c,d]).
    +2> S1 = gb_sets:from_list([d,e,f]).
    +3> S2 = gb_sets:from_list([q,r])
    +4> Sets = [S0, S1, S2].
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gen_event.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (646))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gen_event.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gen_event.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -1175,15 +1175,15 @@
     but it may transform some values.

    Two possible use cases for this callback is to remove sensitive information from the state to prevent it from being printed in log files, or to compact large irrelevant status items -that would only clutter the logs.

    Example:

    format_status(Status) ->
    -  maps:map(
    -    fun(state,State) ->
    -            maps:remove(private_key, State);
    -       (message,{password, _Pass}) ->
    -            {password, removed};
    -       (_,Value) ->
    +that would only clutter the logs.

    Example:

    format_status(Status) ->
    +  maps:map(
    +    fun(state,State) ->
    +            maps:remove(private_key, State);
    +       (message,{password, _Pass}) ->
    +            {password, removed};
    +       (_,Value) ->
                 Value
    -    end, Status).

    Note

    This callback is optional, so event handler modules need not export it. + end, Status).

    Note

    This callback is optional, so event handler modules need not export it. If a handler does not export this function, the gen_event module uses the handler state directly for the purposes described below.

    If this callback is exported but fails, to hide possibly sensitive data, the default function will instead return the fact that /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gen_fsm.xhtml differs (HTML document, ASCII text, with very long lines (879)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gen_fsm.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gen_fsm.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -23,163 +23,163 @@

    Deprecated and replaced by gen_statem in OTP 20.

    Migration to gen_statem

    Here follows a simple example of turning a gen_fsm into a gen_statem. -The example comes from the previous User's Guide for gen_fsm

    -module(code_lock).
    --define(NAME, code_lock).
    +The example comes from the previous User's Guide for gen_fsm

    -module(code_lock).
    +-define(NAME, code_lock).
     %-define(BEFORE_REWRITE, true).
     
    --ifdef(BEFORE_REWRITE).
    --behaviour(gen_fsm).
    +-ifdef(BEFORE_REWRITE).
    +-behaviour(gen_fsm).
     -else.
    --behaviour(gen_statem).
    +-behaviour(gen_statem).
     -endif.
     
    --export([start_link/1, button/1, stop/0]).
    +-export([start_link/1, button/1, stop/0]).
     
    --ifdef(BEFORE_REWRITE).
    --export([init/1, locked/2, open/2, handle_sync_event/4, handle_event/3,
    -     handle_info/3, terminate/3, code_change/4]).
    +-ifdef(BEFORE_REWRITE).
    +-export([init/1, locked/2, open/2, handle_sync_event/4, handle_event/3,
    +     handle_info/3, terminate/3, code_change/4]).
     -else.
    --export([init/1, callback_mode/0, locked/3, open/3,
    -     terminate/3, code_change/4]).
    +-export([init/1, callback_mode/0, locked/3, open/3,
    +     terminate/3, code_change/4]).
     %% Add callback__mode/0
     %% Change arity of the state functions
     %% Remove handle_info/3
     -endif.
     
    --ifdef(BEFORE_REWRITE).
    -start_link(Code) ->
    -    gen_fsm:start_link({local, ?NAME}, ?MODULE, Code, []).
    +-ifdef(BEFORE_REWRITE).
    +start_link(Code) ->
    +    gen_fsm:start_link({local, ?NAME}, ?MODULE, Code, []).
     -else.
    -start_link(Code) ->
    -    gen_statem:start_link({local,?NAME}, ?MODULE, Code, []).
    +start_link(Code) ->
    +    gen_statem:start_link({local,?NAME}, ?MODULE, Code, []).
     -endif.
     
    --ifdef(BEFORE_REWRITE).
    -button(Digit) ->
    -    gen_fsm:send_event(?NAME, {button, Digit}).
    +-ifdef(BEFORE_REWRITE).
    +button(Digit) ->
    +    gen_fsm:send_event(?NAME, {button, Digit}).
     -else.
    -button(Digit) ->
    -    gen_statem:cast(?NAME, {button,Digit}).
    +button(Digit) ->
    +    gen_statem:cast(?NAME, {button,Digit}).
         %% send_event is asynchronous and becomes a cast
     -endif.
     
    --ifdef(BEFORE_REWRITE).
    -stop() ->
    -    gen_fsm:sync_send_all_state_event(?NAME, stop).
    +-ifdef(BEFORE_REWRITE).
    +stop() ->
    +    gen_fsm:sync_send_all_state_event(?NAME, stop).
     -else.
    -stop() ->
    -    gen_statem:call(?NAME, stop).
    +stop() ->
    +    gen_statem:call(?NAME, stop).
         %% sync_send is synchronous and becomes call
         %% all_state is handled by callback code in gen_statem
     -endif.
     
    -init(Code) ->
    -    do_lock(),
    -    Data = #{code => Code, remaining => Code},
    -    {ok, locked, Data}.
    +init(Code) ->
    +    do_lock(),
    +    Data = #{code => Code, remaining => Code},
    +    {ok, locked, Data}.
     
    --ifdef(BEFORE_REWRITE).
    +-ifdef(BEFORE_REWRITE).
     -else.
    -callback_mode() ->
    +callback_mode() ->
         state_functions.
     %% state_functions mode is the mode most similar to
     %% gen_fsm. There is also handle_event mode which is
     %% a fairly different concept.
     -endif.
     
    --ifdef(BEFORE_REWRITE).
    -locked({button, Digit}, Data0) ->
    -    case analyze_lock(Digit, Data0) of
    -    {open = StateName, Data} ->
    -        {next_state, StateName, Data, 10000};
    -    {StateName, Data} ->
    -        {next_state, StateName, Data}
    +-ifdef(BEFORE_REWRITE).
    +locked({button, Digit}, Data0) ->
    +    case analyze_lock(Digit, Data0) of
    +    {open = StateName, Data} ->
    +        {next_state, StateName, Data, 10000};
    +    {StateName, Data} ->
    +        {next_state, StateName, Data}
         end.
     -else.
    -locked(cast, {button,Digit}, Data0) ->
    -    case analyze_lock(Digit, Data0) of
    -    {open = StateName, Data} ->
    -        {next_state, StateName, Data, 10000};
    -    {StateName, Data} ->
    -        {next_state, StateName, Data}
    +locked(cast, {button,Digit}, Data0) ->
    +    case analyze_lock(Digit, Data0) of
    +    {open = StateName, Data} ->
    +        {next_state, StateName, Data, 10000};
    +    {StateName, Data} ->
    +        {next_state, StateName, Data}
         end;
    -locked({call, From}, Msg, Data) ->
    -    handle_call(From, Msg, Data);
    -locked({info, Msg}, StateName, Data) ->
    -    handle_info(Msg, StateName, Data).
    +locked({call, From}, Msg, Data) ->
    +    handle_call(From, Msg, Data);
    +locked({info, Msg}, StateName, Data) ->
    +    handle_info(Msg, StateName, Data).
     %% Arity differs
     %% All state events are dispatched to handle_call and handle_info help
     %% functions. If you want to handle a call or cast event specifically
     %% for this state you would add a special clause for it above.
     -endif.
     
    --ifdef(BEFORE_REWRITE).
    -open(timeout, State) ->
    -     do_lock(),
    -    {next_state, locked, State};
    -open({button,_}, Data) ->
    -    {next_state, locked, Data}.
    --else.
    -open(timeout, _, Data) ->
    -    do_lock(),
    -    {next_state, locked, Data};
    -open(cast, {button,_}, Data) ->
    -    {next_state, locked, Data};
    -open({call, From}, Msg, Data) ->
    -    handle_call(From, Msg, Data);
    -open(info, Msg, Data) ->
    -    handle_info(Msg, open, Data).
    +-ifdef(BEFORE_REWRITE).
    +open(timeout, State) ->
    +     do_lock(),
    +    {next_state, locked, State};
    +open({button,_}, Data) ->
    +    {next_state, locked, Data}.
    +-else.
    +open(timeout, _, Data) ->
    +    do_lock(),
    +    {next_state, locked, Data};
    +open(cast, {button,_}, Data) ->
    +    {next_state, locked, Data};
    +open({call, From}, Msg, Data) ->
    +    handle_call(From, Msg, Data);
    +open(info, Msg, Data) ->
    +    handle_info(Msg, open, Data).
     %% Arity differs
     %% All state events are dispatched to handle_call and handle_info help
     %% functions. If you want to handle a call or cast event specifically
     %% for this state you would add a special clause for it above.
     -endif.
     
    --ifdef(BEFORE_REWRITE).
    -handle_sync_event(stop, _From, _StateName, Data) ->
    -    {stop, normal, ok, Data}.
    +-ifdef(BEFORE_REWRITE).
    +handle_sync_event(stop, _From, _StateName, Data) ->
    +    {stop, normal, ok, Data}.
     
    -handle_event(Event, StateName, Data) ->
    -    {stop, {shutdown, {unexpected, Event, StateName}}, Data}.
    +handle_event(Event, StateName, Data) ->
    +    {stop, {shutdown, {unexpected, Event, StateName}}, Data}.
     
    -handle_info(Info, StateName, Data) ->
    -    {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.
    +handle_info(Info, StateName, Data) ->
    +    {stop, {shutdown, {unexpected, Info, StateName}}, StateName, Data}.
     -else.
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gen_server.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (656))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gen_server.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gen_server.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -1273,15 +1273,15 @@
     but it may transform some values.

    Two possible use cases for this callback is to remove sensitive information from the state to prevent it from being printed in log files, or to compact large irrelevant status items -that would only clutter the logs.

    Example:

    format_status(Status) ->
    -  maps:map(
    -    fun(state,State) ->
    -            maps:remove(private_key, State);
    -       (message,{password, _Pass}) ->
    -            {password, removed};
    -       (_,Value) ->
    +that would only clutter the logs.

    Example:

    format_status(Status) ->
    +  maps:map(
    +    fun(state,State) ->
    +            maps:remove(private_key, State);
    +       (message,{password, _Pass}) ->
    +            {password, removed};
    +       (_,Value) ->
                 Value
    -    end, Status).

    Note

    This callback is optional, so callback modules need not export it. The + end, Status).

    Note

    This callback is optional, so callback modules need not export it. The gen_server module provides a default implementation of this function that returns the callback module state.

    If this callback is exported but fails, to hide possibly sensitive data, /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gen_statem.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (956)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gen_statem.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/gen_statem.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -70,7 +70,7 @@ depending on callback mode Release upgrade/downgrade -(code change) +(code change) -----> Module:code_change/4

    State callback

    The state callback for a specific state in a gen_statem is the callback function that is called for all events in this state. It is selected depending on which callback mode @@ -178,97 +178,97 @@ on --> off : push\n* Reply 'off'

    Not shown in the state diagram:

    • The API function push() generates an event push of type call.
    • The API function get_count() generates an event get_count of type call that is handled in all states by replying with the current count value.
    • Unknown events are ignored and discarded.
    • There is boilerplate code for start, stop, terminate, code change, -init, to set the callback mode to state_functions, etc...

    Pushbutton Code

    The following is the complete callback module file pushbutton.erl:

    -module(pushbutton).
    --behaviour(gen_statem).
    +init, to set the callback mode to state_functions, etc...

    Pushbutton Code

    The following is the complete callback module file pushbutton.erl:

    -module(pushbutton).
    +-behaviour(gen_statem).
     
    --export([start/0,push/0,get_count/0,stop/0]).
    --export([terminate/3,code_change/4,init/1,callback_mode/0]).
    --export([on/3,off/3]).
    +-export([start/0,push/0,get_count/0,stop/0]).
    +-export([terminate/3,code_change/4,init/1,callback_mode/0]).
    +-export([on/3,off/3]).
     
    -name() -> pushbutton_statem. % The registered server name
    +name() -> pushbutton_statem. % The registered server name
     
     %% API.  This example uses a registered name name()
     %% and does not link to the caller.
    -start() ->
    -    gen_statem:start({local,name()}, ?MODULE, [], []).
    -push() ->
    -    gen_statem:call(name(), push).
    -get_count() ->
    -    gen_statem:call(name(), get_count).
    -stop() ->
    -    gen_statem:stop(name()).
    +start() ->
    +    gen_statem:start({local,name()}, ?MODULE, [], []).
    +push() ->
    +    gen_statem:call(name(), push).
    +get_count() ->
    +    gen_statem:call(name(), get_count).
    +stop() ->
    +    gen_statem:stop(name()).
     
     %% Mandatory callback functions
    -terminate(_Reason, _State, _Data) ->
    +terminate(_Reason, _State, _Data) ->
         void.
    -code_change(_Vsn, State, Data, _Extra) ->
    -    {ok,State,Data}.
    -init([]) ->
    +code_change(_Vsn, State, Data, _Extra) ->
    +    {ok,State,Data}.
    +init([]) ->
         %% Set the initial state + data.  Data is used only as a counter.
         State = off, Data = 0,
    -    {ok,State,Data}.
    -callback_mode() -> state_functions.
    +    {ok,State,Data}.
    +callback_mode() -> state_functions.
     
     %%% state callback(s)
     
    -off({call,From}, push, Data) ->
    +off({call,From}, push, Data) ->
         %% Go to 'on', increment count and reply
         %% that the resulting status is 'on'
    -    {next_state,on,Data+1,[{reply,From,on}]};
    -off(EventType, EventContent, Data) ->
    -    handle_event(EventType, EventContent, Data).
    +    {next_state,on,Data+1,[{reply,From,on}]};
    +off(EventType, EventContent, Data) ->
    +    handle_event(EventType, EventContent, Data).
     
    -on({call,From}, push, Data) ->
    +on({call,From}, push, Data) ->
         %% Go to 'off' and reply that the resulting status is 'off'
    -    {next_state,off,Data,[{reply,From,off}]};
    -on(EventType, EventContent, Data) ->
    -    handle_event(EventType, EventContent, Data).
    +    {next_state,off,Data,[{reply,From,off}]};
    +on(EventType, EventContent, Data) ->
    +    handle_event(EventType, EventContent, Data).
     
     %% Handle events common to all states
    -handle_event({call,From}, get_count, Data) ->
    +handle_event({call,From}, get_count, Data) ->
         %% Reply with the current count
    -    {keep_state,Data,[{reply,From,Data}]};
    -handle_event(_, _, Data) ->
    +    {keep_state,Data,[{reply,From,Data}]};
    +handle_event(_, _, Data) ->
         %% Ignore all other events
    -    {keep_state,Data}.

    The following is a shell session when running it:

    1> pushbutton:start().
    -{ok,<0.36.0>}
    -2> pushbutton:get_count().
    +    {keep_state,Data}.

    The following is a shell session when running it:

    1> pushbutton:start().
    +{ok,<0.36.0>}
    +2> pushbutton:get_count().
     0
    -3> pushbutton:push().
    +3> pushbutton:push().
     on
    -4> pushbutton:get_count().
    +4> pushbutton:get_count().
     1
    -5> pushbutton:push().
    +5> pushbutton:push().
     off
    -6> pushbutton:get_count().
    +6> pushbutton:get_count().
     1
    -7> pushbutton:stop().
    +7> pushbutton:stop().
     ok
    -8> pushbutton:push().
    +8> pushbutton:push().
     ** exception exit: {noproc,{gen_statem,call,[pushbutton_statem,push,infinity]}}
          in function  gen:do_for_proc/2 (gen.erl, line 261)
          in call from gen_statem:call/3 (gen_statem.erl, line 386)

    To compare styles, here follows the same example using callback mode handle_event_function, or rather, the code to replace after function init/1 -of the pushbutton.erl example file above:

    callback_mode() -> handle_event_function.
    +of the pushbutton.erl example file above:

    callback_mode() -> handle_event_function.
     
     %%% state callback(s)
     
    -handle_event({call,From}, push, off, Data) ->
    +handle_event({call,From}, push, off, Data) ->
         %% Go to 'on', increment count and reply
         %% that the resulting status is 'on'
    -    {next_state,on,Data+1,[{reply,From,on}]};
    -handle_event({call,From}, push, on, Data) ->
    +    {next_state,on,Data+1,[{reply,From,on}]};
    +handle_event({call,From}, push, on, Data) ->
         %% Go to 'off' and reply that the resulting status is 'off'
    -    {next_state,off,Data,[{reply,From,off}]};
    +    {next_state,off,Data,[{reply,From,off}]};
     %%
     %% Event handling common to all states
    -handle_event({call,From}, get_count, State, Data) ->
    +handle_event({call,From}, get_count, State, Data) ->
         %% Reply with the current count
    -    {next_state,State,Data,[{reply,From,Data}]};
    -handle_event(_, _, State, Data) ->
    +    {next_state,State,Data,[{reply,From,Data}]};
    +handle_event(_, _, State, Data) ->
         %% Ignore all other events
    -    {next_state,State,Data}.

    Note

    API changes

    • This behavior appeared in Erlang/OTP 19.0 as experimental.
    • In OTP 19.1 a backwards incompatible change of the return tuple from + {next_state,State,Data}.

    Note

    API changes

    • This behavior appeared in Erlang/OTP 19.0 as experimental.
    • In OTP 19.1 a backwards incompatible change of the return tuple from Module:init/1 was made, the mandatory callback function Module:callback_mode/0 was introduced, @@ -3025,15 +3025,15 @@ containing the same keys as the input map, but it may transform some values.

      One use case for this function is to return compact alternative state representations to avoid having large state terms printed in log files. -Another is to hide sensitive data from being written to the error log.

      Example:

      format_status(Status) ->
      -  maps:map(
      -    fun(state,State) ->
      -            maps:remove(private_key, State);
      -       (message,{password, _Pass}) ->
      -            {password, removed};
      -       (_,Value) ->
      +Another is to hide sensitive data from being written to the error log.

      Example:

      format_status(Status) ->
      +  maps:map(
      +    fun(state,State) ->
      +            maps:remove(private_key, State);
      +       (message,{password, _Pass}) ->
      +            {password, removed};
      +       (_,Value) ->
                   Value
      -    end, Status).

      Note

      This callback is optional, so a callback module does not need + end, Status).

      Note

      This callback is optional, so a callback module does not need to export it. The gen_statem module provides a default implementation of this function that returns {State, Data}.

      If this callback is exported but fails, to hide possibly sensitive data, the default function will instead return {State, Info}, @@ -3207,8 +3207,8 @@ to initialize the implementation state and server data.

      Args is the Args argument provided to that start function.

      Note

      Note that if the gen_statem is started through proc_lib and enter_loop/4,5,6, this callback will never be called. Since this callback is not optional -it can in that case be implemented as:

      -spec init(_) -> no_return().
      -init(Args) -> erlang:error(not_implemented, [Args]).
      +it can in that case be implemented as:

      -spec init(_) -> no_return().
      +init(Args) -> erlang:error(not_implemented, [Args]).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/io_lib.xhtml differs (HTML document, ASCII text, with very long lines (824)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/io_lib.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/io_lib.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -1176,8 +1176,8 @@ input is needed to complete the original format string. RestFormat is the remaining format string, Nchars is the number of characters scanned, and InputStack is the reversed list of inputs matched up to that point.

  • {error, What} - The read operation failed and parameter What gives a -hint about the error.

  • Example:

    3> io_lib:fread("~f~f~f", "15.6 17.3e-6 24.5").
    -{ok,[15.6,1.73e-5,24.5],[]}
    +hint about the error.

    Example:

    3> io_lib:fread("~f~f~f", "15.6 17.3e-6 24.5").
    +{ok,[15.6,1.73e-5,24.5],[]}
    @@ -1686,11 +1686,11 @@ "...".

    Depth defaults to -1, which means no limitation. Option CharsLimit puts a soft limit on the number of characters returned. When the number of characters is reached, remaining structures are replaced by "...". CharsLimit defaults to -1, -which means no limit on the number of characters returned.

    Example:

    1> lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9})).
    +which means no limit on the number of characters returned.

    Example:

    1> lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9})).
     "{1,[2],[3],[4,5],6,7,8,9}"
    -2> lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9}, 5)).
    +2> lists:flatten(io_lib:write({1,[2],[3],[4,5],6,7,8,9}, 5)).
     "{1,[2],[3],[...],...}"
    -3> lists:flatten(io_lib:write({[1,2,3],[4,5],6,7,8,9}, [{chars_limit,20}])).
    +3> lists:flatten(io_lib:write({[1,2,3],[4,5],6,7,8,9}, [{chars_limit,20}])).
     "{[1,2|...],[4|...],...}"
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/io_protocol.xhtml differs (HTML document, ASCII text, with very long lines (1563)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/io_protocol.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/io_protocol.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -32,8 +32,8 @@ ever present in the client. Any I/O server can be used together with any client code, and the client code does not need to be aware of the I/O device that the I/O server communicates with.

    Protocol Basics

    As described in Robert's paper, I/O servers and clients communicate using -io_request/io_reply tuples as follows:

    {io_request, From, ReplyAs, Request}
    -{io_reply, ReplyAs, Reply}

    The client sends an io_request tuple to the I/O server and the server +io_request/io_reply tuples as follows:

    {io_request, From, ReplyAs, Request}
    +{io_reply, ReplyAs, Reply}

    The client sends an io_request tuple to the I/O server and the server eventually sends a corresponding io_reply tuple.

    • From is the pid/0 of the client, the process which the I/O server sends the I/O reply to.

    • ReplyAs can be any datum and is returned in the corresponding io_reply. The io module monitors the I/O server and uses the monitor reference as @@ -44,8 +44,8 @@ io_reply. The reply can be sent from any process, not necessarily the actual I/O server.

    • Request and Reply are described below.

    When an I/O server receives an io_request tuple, it acts upon the Request part and eventually sends an io_reply tuple with the corresponding Reply -part.

    Output Requests

    To output characters on an I/O device, the following Requests exist:

    {put_chars, Encoding, Characters}
    -{put_chars, Encoding, Module, Function, Args}
    • Encoding is unicode or latin1, meaning that the characters are (in case +part.

      Output Requests

      To output characters on an I/O device, the following Requests exist:

      {put_chars, Encoding, Characters}
      +{put_chars, Encoding, Module, Function, Args}
      • Encoding is unicode or latin1, meaning that the characters are (in case of binaries) encoded as UTF-8 or ISO Latin-1 (pure bytes). A well-behaved I/O server is also to return an error indication if list elements contain integers > 255 when Encoding is set to latin1.

        Notice that this does not in any way tell how characters are to be put on the @@ -64,8 +64,8 @@ the function returns anything else than a binary or list, or throws an exception, an error is to be sent back to the client.

      The I/O server replies to the client with an io_reply tuple, where element Reply is one of:

      ok
      -{error, Error}
      • Error describes the error to the client, which can do whatever it wants with -it. The io module typically returns it "as is".

      Input Requests

      To read characters from an I/O device, the following Requests exist:

      {get_until, Encoding, Prompt, Module, Function, ExtraArgs}
      • Encoding denotes how data is to be sent back to the client and what data is +{error, Error}

    • Error describes the error to the client, which can do whatever it wants with +it. The io module typically returns it "as is".

    Input Requests

    To read characters from an I/O device, the following Requests exist:

    {get_until, Encoding, Prompt, Module, Function, ExtraArgs}
    • Encoding denotes how data is to be sent back to the client and what data is sent to the function denoted by Module/Function/ExtraArgs. If the function supplied returns data as a list, the data is converted to this encoding. If the function supplied returns data in some other format, no @@ -81,8 +81,8 @@ nothing being written to the I/O device).

    • Module, Function, and ExtraArgs denote a function and arguments to determine when enough data is written. The function is to take two more arguments, the last state, and a list of characters. The function is to return -one of:

      {done, Result, RestChars}
      -{more, Continuation}

      Result can be any Erlang term, but if it is a list/0, the I/O server can +one of:

      {done, Result, RestChars}
      +{more, Continuation}

      Result can be any Erlang term, but if it is a list/0, the I/O server can convert it to a binary/0 of appropriate format before returning it to the client, if the I/O server is set in binary mode (see below).

      The function is called with the data the I/O server finds on its I/O device, returning one of:

      • {done, Result, RestChars} when enough data is read. In this case Result @@ -92,38 +92,38 @@ characters are available. When no more characters are available, the function must return {done, eof, Rest}. The initial state is the empty list. The data when an end of file is reached on the IO device is the atom eof.

        An emulation of the get_line request can be (inefficiently) implemented -using the following functions:

        -module(demo).
        --export([until_newline/3, get_line/1]).
        +using the following functions:

        -module(demo).
        +-export([until_newline/3, get_line/1]).
         
        -until_newline(_ThisFar,eof,_MyStopCharacter) ->
        -    {done,eof,[]};
        -until_newline(ThisFar,CharList,MyStopCharacter) ->
        +until_newline(_ThisFar,eof,_MyStopCharacter) ->
        +    {done,eof,[]};
        +until_newline(ThisFar,CharList,MyStopCharacter) ->
             case
        -        lists:splitwith(fun(X) -> X =/= MyStopCharacter end,  CharList)
        +        lists:splitwith(fun(X) -> X =/= MyStopCharacter end,  CharList)
             of
        -  {L,[]} ->
        -            {more,ThisFar++L};
        -  {L2,[MyStopCharacter|Rest]} ->
        -      {done,ThisFar++L2++[MyStopCharacter],Rest}
        +  {L,[]} ->
        +            {more,ThisFar++L};
        +  {L2,[MyStopCharacter|Rest]} ->
        +      {done,ThisFar++L2++[MyStopCharacter],Rest}
             end.
         
        -get_line(IoServer) ->
        -    IoServer ! {io_request,
        -                self(),
        +get_line(IoServer) ->
        +    IoServer ! {io_request,
        +                self(),
                         IoServer,
        -                {get_until, unicode, '', ?MODULE, until_newline, [$\n]}},
        +                {get_until, unicode, '', ?MODULE, until_newline, [$\n]}},
             receive
        -        {io_reply, IoServer, Data} ->
        +        {io_reply, IoServer, Data} ->
               Data
             end.

        Notice that the last element in the Request tuple ([$\n]) is appended to the argument list when the function is called. The function is to be called like apply(Module, Function, [ State, Data | ExtraArgs ]) by -the I/O server.

      A fixed number of characters is requested using the following Request:

      {get_chars, Encoding, Prompt, N}
      • Encoding and Prompt as for get_until.
      • N is the number of characters to be read from the I/O device.

      A single line (as in former example) is requested with the following Request:

      {get_line, Encoding, Prompt}
      • Encoding and Prompt as for get_until.

      Clearly, get_chars and get_line could be implemented with the get_until +the I/O server.

    A fixed number of characters is requested using the following Request:

    {get_chars, Encoding, Prompt, N}
    • Encoding and Prompt as for get_until.
    • N is the number of characters to be read from the I/O device.

    A single line (as in former example) is requested with the following Request:

    {get_line, Encoding, Prompt}
    • Encoding and Prompt as for get_until.

    Clearly, get_chars and get_line could be implemented with the get_until request (and indeed they were originally), but demands for efficiency have made these additions necessary.

    The I/O server replies to the client with an io_reply tuple, where element Reply is one of:

    Data
     eof
    -{error, Error}
    • Data is the characters read, in list or binary form (depending on the I/O +{error, Error}
    • Data is the characters read, in list or binary form (depending on the I/O server mode, see the next section).
    • eof is returned when input end is reached and no more data is available to the client process.
    • Error describes the error to the client, which can do whatever it wants with it. The io module typically returns it as is.

    I/O Server Modes

    Demands for efficiency when reading data from an I/O server has not only lead to @@ -143,164 +143,164 @@ This is done in the example in section An Annotated and Working Example I/O Server.

    An I/O server in binary mode affects the data sent to the client, so that it must be able to handle binary data. For convenience, the modes of an I/O server -can be set and retrieved using the following I/O requests:

    {setopts, Opts}
    • Opts is a list of options in the format recognized by the proplists +can be set and retrieved using the following I/O requests:

      {setopts, Opts}
      • Opts is a list of options in the format recognized by the proplists module (and by the I/O server).

      As an example, the I/O server for the interactive shell (in group.erl) -understands the following options:

      {binary, boolean()} (or binary/list)
      -{echo, boolean()}
      -{expand_fun, fun()}
      -{encoding, unicode/latin1} (or unicode/latin1)

      Options binary and encoding are common for all I/O servers in OTP, while +understands the following options:

      {binary, boolean()} (or binary/list)
      +{echo, boolean()}
      +{expand_fun, fun()}
      +{encoding, unicode/latin1} (or unicode/latin1)

      Options binary and encoding are common for all I/O servers in OTP, while echo and expand are valid only for this I/O server. Option unicode notifies how characters are put on the physical I/O device, that is, if the terminal itself is Unicode-aware. It does not affect how characters are sent in the I/O protocol, where each request contains encoding information for the provided or returned data.

      The I/O server is to send one of the following as Reply:

      ok
      -{error, Error}

      An error (preferably enotsup) is to be expected if the option is not supported +{error, Error}

    An error (preferably enotsup) is to be expected if the option is not supported by the I/O server (like if an echo option is sent in a setopts request to a plain file).

    To retrieve options, the following request is used:

    getopts

    This request asks for a complete list of all options supported by the I/O server as well as their current values.

    The I/O server replies:

    OptList
    -{error, Error}
    • OptList is a list of tuples {Option, Value}, where Option always is an +{error, Error}
    • OptList is a list of tuples {Option, Value}, where Option always is an atom.

    Multiple I/O Requests

    The Request element can in itself contain many Requests by using the -following format:

    {requests, Requests}
    • Requests is a list of valid io_request tuples for the protocol. They must +following format:

      {requests, Requests}
      • Requests is a list of valid io_request tuples for the protocol. They must be executed in the order that they appear in the list. The execution is to continue until one of the requests results in an error or the list is consumed. The result of the last request is sent back to the client.

      The I/O server can, for a list of requests, send any of the following valid results in the reply, depending on the requests in the list:

      ok
      -{ok, Data}
      -{ok, Options}
      -{error, Error}

      Optional I/O Request

      The following I/O request is optional to implement and a client is to be -prepared for an error return:

      {get_geometry, Geometry}
      • Geometry is the atom rows or the atom columns.

      The I/O server is to send one of the following as Reply:

      N
      -{error, Error}
      • N is the number of character rows or columns that the I/O device has, if +{ok, Data} +{ok, Options} +{error, Error}

    Optional I/O Request

    The following I/O request is optional to implement and a client is to be +prepared for an error return:

    {get_geometry, Geometry}
    • Geometry is the atom rows or the atom columns.

    The I/O server is to send one of the following as Reply:

    N
    +{error, Error}
    • N is the number of character rows or columns that the I/O device has, if applicable to the I/O device handled by the I/O server, otherwise {error, enotsup} is a good answer.

    Unimplemented Request Types

    If an I/O server encounters a request that it does not recognize (that is, the io_request tuple has the expected format, but the Request is unknown), the -I/O server is to send a valid reply with the error tuple:

    {error, request}

    This makes it possible to extend the protocol with optional requests and for the +I/O server is to send a valid reply with the error tuple:

    {error, request}

    This makes it possible to extend the protocol with optional requests and for the clients to be somewhat backward compatible.

    An Annotated and Working Example I/O Server

    An I/O server is any process capable of handling the I/O protocol. There is no generic I/O server behavior, but could well be. The framework is simple, a process handling incoming requests, usually both I/O-requests and other I/O device-specific requests (positioning, closing, and so on).

    The example I/O server stores characters in an ETS table, making up a fairly crude RAM file.

    The module begins with the usual directives, a function to start the I/O server -and a main loop handling the requests:

    -module(ets_io_server).
    +and a main loop handling the requests:

    -module(ets_io_server).
     
    --export([start_link/0, init/0, loop/1, until_newline/3, until_enough/3]).
    +-export([start_link/0, init/0, loop/1, until_newline/3, until_enough/3]).
     
    --define(CHARS_PER_REC, 10).
    +-define(CHARS_PER_REC, 10).
     
    --record(state, {
    +-record(state, {
     	  table,
     	  position, % absolute
     	  mode % binary | list
    -	 }).
    +	 }).
     
    -start_link() ->
    -    spawn_link(?MODULE,init,[]).
    +start_link() ->
    +    spawn_link(?MODULE,init,[]).
     
    -init() ->
    -    Table = ets:new(noname,[ordered_set]),
    -    ?MODULE:loop(#state{table = Table, position = 0, mode=list}).
    +init() ->
    +    Table = ets:new(noname,[ordered_set]),
    +    ?MODULE:loop(#state{table = Table, position = 0, mode=list}).
     
    -loop(State) ->
    +loop(State) ->
         receive
    -	{io_request, From, ReplyAs, Request} ->
    -	    case request(Request,State) of
    -		{Tag, Reply, NewState} when Tag =:= ok; Tag =:= error ->
    -		    reply(From, ReplyAs, Reply),
    -		    ?MODULE:loop(NewState);
    -		{stop, Reply, _NewState} ->
    -		    reply(From, ReplyAs, Reply),
    -		    exit(Reply)
    +	{io_request, From, ReplyAs, Request} ->
    +	    case request(Request,State) of
    +		{Tag, Reply, NewState} when Tag =:= ok; Tag =:= error ->
    +		    reply(From, ReplyAs, Reply),
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/io.xhtml differs (HTML document, ASCII text, with very long lines (876))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/io.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/io.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -36,7 +36,7 @@
     binaries instead of lists. The binaries are encoded in UTF-8.

    To work with binaries in ISO Latin-1 encoding, use the file module instead.

    For conversion functions between character encodings, see the unicode module.

    Error Information

    The ErrorInfo mentioned in this module is the standard ErrorInfo structure -that is returned from all I/O modules. It has the following format:

    {ErrorLocation, Module, ErrorDescriptor}

    A string that describes the error is obtained with the following call:

    Module:format_error(ErrorDescriptor)
    +that is returned from all I/O modules. It has the following format:

    {ErrorLocation, Module, ErrorDescriptor}

    A string that describes the error is obtained with the following call:

    Module:format_error(ErrorDescriptor)
    @@ -1077,12 +1077,12 @@ no IoDevice argument is specified in the function calls in this module.

    It is sometimes desirable to use an explicit IoDevice argument that refers to the default I/O device. This is the case with functions that can access either a file or the default I/O device. The atom standard_io has this -special meaning. The following example illustrates this:

    27> io:read('enter>').
    +special meaning. The following example illustrates this:

    27> io:read('enter>').
     enter>foo.
    -{ok,foo}
    -28> io:read(standard_io, 'enter>').
    +{ok,foo}
    +28> io:read(standard_io, 'enter>').
     enter>bar.
    -{ok,bar}

    By default all I/O sent to standard_io will end up in the user +{ok,bar}

    By default all I/O sent to standard_io will end up in the user I/O device of the node that spawned the calling process.

    standard_io is an alias for group_leader/0, so in order to change where the default input/output requests are sent you can change the group leader of the current process using @@ -1352,33 +1352,33 @@ whitespace characters are stripped. An Erlang string (list of characters) is returned.

    If Unicode translation is in effect (~ts), characters > 255 are accepted, otherwise not. With the translation modifier, the returned list can as a -consequence also contain integers > 255:

    1> io:fread("Prompt> ","~s").
    +consequence also contain integers > 255:

    1> io:fread("Prompt> ","~s").
     Prompt> <Characters beyond latin1 range not printable in this medium>
    -{error,{fread,string}}
    -2> io:fread("Prompt> ","~ts").
    +{error,{fread,string}}
    +2> io:fread("Prompt> ","~ts").
     Prompt> <Characters beyond latin1 range not printable in this medium>
    -{ok,[[1091,1085,1080,1094,1086,1076,1077]]}
  • a - Similar to s, but the resulting string is converted into an +{ok,[[1091,1085,1080,1094,1086,1076,1077]]}

  • a - Similar to s, but the resulting string is converted into an atom.

  • c - The number of characters equal to the field width are read (default is 1) and returned as an Erlang string. However, leading and trailing whitespace characters are not omitted as they are with s. All -characters are returned.

    The Unicode translation modifier works as with s:

    1> io:fread("Prompt> ","~c").
    +characters are returned.

    The Unicode translation modifier works as with s:

    1> io:fread("Prompt> ","~c").
     Prompt> <Character beyond latin1 range not printable in this medium>
    -{error,{fread,string}}
    -2> io:fread("Prompt> ","~tc").
    +{error,{fread,string}}
    +2> io:fread("Prompt> ","~tc").
     Prompt> <Character beyond latin1 range not printable in this medium>
    -{ok,[[1091]]}
  • l - Returns the number of characters that have been scanned up to that +{ok,[[1091]]}

  • l - Returns the number of characters that have been scanned up to that point, including whitespace characters.

  • The function returns:
    • {ok, Terms} - The read was successful and Terms is the list of successfully matched and read items.

    • eof - End of file was encountered.

    • {error, FreadError} - The reading failed and FreadError gives a hint about the error.

    • {error, ErrorDescription} - The read operation failed and parameter -ErrorDescription gives a hint about the error.

    Examples:

    20> io:fread('enter>', "~f~f~f").
    +ErrorDescription gives a hint about the error.

    Examples:

    20> io:fread('enter>', "~f~f~f").
     enter>1.9 35.5e3 15.0
    -{ok,[1.9,3.55e4,15.0]}
    -21> io:fread('enter>', "~10f~d").
    +{ok,[1.9,3.55e4,15.0]}
    +21> io:fread('enter>', "~10f~d").
     enter>     5.67899
    -{ok,[5.678,99]}
    -22> io:fread('enter>', ":~10s:~10c:").
    +{ok,[5.678,99]}
    +22> io:fread('enter>', ":~10s:~10c:").
     enter>:   alan   :   joe    :
    -{ok, ["alan", "   joe    "]}
    +
    {ok, ["alan", " joe "]}
    @@ -1467,7 +1467,7 @@ the output device, and control sequences for formatting, see below. If Format is an atom or a binary, it is first converted to a list with the aid of atom_to_list/1 or -binary_to_list/1. Example:

    1> io:fwrite("Hello world!~n", []).
    +binary_to_list/1. Example:

    1> io:fwrite("Hello world!~n", []).
     Hello world!
     ok

    The general format of a control sequence is ~F.P.PadModC.

    The character C determines the type of control sequence to be used. It is the only required field. All of F, P, Pad, and Mod are optional. For @@ -1485,25 +1485,25 @@ padding character is ' ' (space).

  • Mod is the control sequence modifier. This is one or more characters that change the interpretation of Data.

    The current modifiers are:

    • t - For Unicode translation.

    • l - For stopping p and P from detecting printable characters.

    • k - For use with p, P, w, and W to format maps in map-key ordered order (see maps:iterator_order/0).

    • K - Similar to k, for formatting maps in map-key order, but takes an -extra argument that specifies the maps:iterator_order/0.

      For example:

      > M = #{ a => 1, b => 2 }.
      -#{a => 1,b => 2}
      -> io:format("~Kp~n", [reversed, M]).
      -#{b => 2,a => 1}
      +extra argument that specifies the maps:iterator_order/0.

      For example:

      > M = #{ a => 1, b => 2 }.
      +#{a => 1,b => 2}
      +> io:format("~Kp~n", [reversed, M]).
      +#{b => 2,a => 1}
       ok
  • If F, P, or Pad is a * character, the next argument in Data is used as -the value. For example:

    1> io:fwrite("~*.*.0f~n",[9, 5, 3.14159265]).
    +the value. For example:

    1> io:fwrite("~*.*.0f~n",[9, 5, 3.14159265]).
     003.14159
    -ok

    To use a literal * character as Pad, it must be passed as an argument:

    2> io:fwrite("~*.*.*f~n",[9, 5, $*, 3.14159265]).
    +ok

    To use a literal * character as Pad, it must be passed as an argument:

    2> io:fwrite("~*.*.*f~n",[9, 5, $*, 3.14159265]).
     **3.14159
     ok

    Available control sequences:

    • ~ - Character ~ is written.

    • c - The argument is a number that is interpreted as an ASCII code. The precision is the number of times the character is printed and defaults to the -field width, which in turn defaults to 1. Example:

      1> io:fwrite("|~10.5c|~-10.5c|~5c|~n", [$a, $b, $c]).
      +field width, which in turn defaults to 1. Example:

      1> io:fwrite("|~10.5c|~-10.5c|~5c|~n", [$a, $b, $c]).
       |     aaaaa|bbbbb     |ccccc|
       ok

      If the Unicode translation modifier (t) is in effect, the integer argument can be any number representing a valid Unicode codepoint, otherwise it is to -be an integer less than or equal to 255, otherwise it is masked with 16#FF:

      2> io:fwrite("~tc~n",[1024]).
      -\x{400}
      +be an integer less than or equal to 255, otherwise it is masked with 16#FF:

      2> io:fwrite("~tc~n",[1024]).
      +\x{400}
       ok
      -3> io:fwrite("~c~n",[1024]).
      +3> io:fwrite("~c~n",[1024]).
       ^@
       ok
    • f - The argument is a float that is written as [-]ddd.ddd, where the precision is the number of digits after the decimal point. The default @@ -1521,18 +1521,18 @@ binaries are in UTF-8. The characters are printed without quotes. The string is first truncated by the specified precision and then padded and justified to the specified field width. The default precision is the field width.

      This format can be used for printing any object and truncating the output so -it fits a specified field:

      1> io:fwrite("|~10w|~n", [{hey, hey, hey}]).
      +it fits a specified field:

      1> io:fwrite("|~10w|~n", [{hey, hey, hey}]).
       |**********|
       ok
      -2> io:fwrite("|~10s|~n", [io_lib:write({hey, hey, hey})]).
      -|{hey,hey,h|
      -3> io:fwrite("|~-10.8s|~n", [io_lib:write({hey, hey, hey})]).
      -|{hey,hey  |
      +2> io:fwrite("|~10s|~n", [io_lib:write({hey, hey, hey})]).
      +|{hey,hey,h|
      +3> io:fwrite("|~-10.8s|~n", [io_lib:write({hey, hey, hey})]).
      +|{hey,hey  |
       ok

      A list with integers > 255 is considered an error if the Unicode translation -modifier is not specified:

      4> io:fwrite("~ts~n",[[1024]]).
      -\x{400}
      +modifier is not specified:

      4> io:fwrite("~ts~n",[[1024]]).
      +\x{400}
       ok
      -5> io:fwrite("~s~n",[[1024]]).
      +5> io:fwrite("~s~n",[[1024]]).
       ** exception error: bad argument
            in function  io:format/3
               called as io:format(<0.53.0>,"~s~n",[[1024]])
    • w - Writes data with the standard syntax. This is used to output Erlang @@ -1543,122 +1543,122 @@ breaks terms whose printed representation is longer than one line into many lines and indents each line sensibly. Left-justification is not supported. It also tries to detect flat lists of printable characters and output these as -strings. For example:

      1> T = [{attributes,[[{id,age,1.50000},{mode,explicit},
      -{typename,"INTEGER"}], [{id,cho},{mode,explicit},{typename,'Cho'}]]},
      -{typename,'Person'},{tag,{'PRIVATE',3}},{mode,implicit}].
      +strings. For example:

      1> T = [{attributes,[[{id,age,1.50000},{mode,explicit},
      +{typename,"INTEGER"}], [{id,cho},{mode,explicit},{typename,'Cho'}]]},
      +{typename,'Person'},{tag,{'PRIVATE',3}},{mode,implicit}].
       ...
      -2> io:fwrite("~w~n", [T]).
      -[{attributes,[[{id,age,1.5},{mode,explicit},{typename,
      -[73,78,84,69,71,69,82]}],[{id,cho},{mode,explicit},{typena
      -me,'Cho'}]]},{typename,'Person'},{tag,{'PRIVATE',3}},{mode
      -,implicit}]
      +2> io:fwrite("~w~n", [T]).
      +[{attributes,[[{id,age,1.5},{mode,explicit},{typename,
      +[73,78,84,69,71,69,82]}],[{id,cho},{mode,explicit},{typena
      +me,'Cho'}]]},{typename,'Person'},{tag,{'PRIVATE',3}},{mode
      +,implicit}]
       ok
      -3> io:fwrite("~62p~n", [T]).
      -[{attributes,[[{id,age,1.5},
      -               {mode,explicit},
      -               {typename,"INTEGER"}],
      -              [{id,cho},{mode,explicit},{typename,'Cho'}]]},
      - {typename,'Person'},
      - {tag,{'PRIVATE',3}},
      - {mode,implicit}]
      +3> io:fwrite("~62p~n", [T]).
      +[{attributes,[[{id,age,1.5},
      +               {mode,explicit},
      +               {typename,"INTEGER"}],
      +              [{id,cho},{mode,explicit},{typename,'Cho'}]]},
      + {typename,'Person'},
      + {tag,{'PRIVATE',3}},
      + {mode,implicit}]
       ok

      The field width specifies the maximum line length. It defaults to 80. The precision specifies the initial indentation of the term. It defaults to the number of characters printed on this line in the same call to write/1 or -format/1,2,3. For example, using T above:

      4> io:fwrite("Here T = ~62p~n", [T]).
      -Here T = [{attributes,[[{id,age,1.5},
      -                        {mode,explicit},
      -                        {typename,"INTEGER"}],
      -                       [{id,cho},
      -                        {mode,explicit},
      -                        {typename,'Cho'}]]},
      -          {typename,'Person'},
      -          {tag,{'PRIVATE',3}},
      -          {mode,implicit}]
      +format/1,2,3. For example, using T above:

      4> io:fwrite("Here T = ~62p~n", [T]).
      /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/json.xhtml differs (HTML document, ASCII text, with very long lines (3329))
      --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/json.xhtml	2026-08-05 05:56:49.000000000 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/json.xhtml	2026-08-05 05:56:49.000000000 +0000
      @@ -877,8 +877,8 @@
       
             
       
      -

      Parses a JSON value from Binary.

      Supports basic data mapping:

      JSONErlang
      Numberinteger() | float()
      Booleantrue | false
      Nullnull
      Stringbinary()
      Object#{binary() => _}

      Errors

      • error(unexpected_end) if Binary contains incomplete JSON value
      • error({invalid_byte, Byte}) if Binary contains unexpected byte or invalid UTF-8 byte
      • error({unexpected_sequence, Bytes}) if Binary contains invalid UTF-8 escape

      Example

      > json:decode(<<"{\"foo\": 1}">>).
      -#{<<"foo">> => 1}
      +

      Parses a JSON value from Binary.

      Supports basic data mapping:

      JSONErlang
      Numberinteger() | float()
      Booleantrue | false
      Nullnull
      Stringbinary()
      Object#{binary() => _}

      Errors

      • error(unexpected_end) if Binary contains incomplete JSON value
      • error({invalid_byte, Byte}) if Binary contains unexpected byte or invalid UTF-8 byte
      • error({unexpected_sequence, Bytes}) if Binary contains invalid UTF-8 escape

      Example

      > json:decode(<<"{\"foo\": 1}">>).
      +#{<<"foo">> => 1}
    @@ -912,9 +912,9 @@ can be customized with the callbacks specified in Decoders. The callbacks will use the Acc value as the initial accumulator.

    Any leftover, unparsed data in Binary will be returned.

    Default callbacks

    All callbacks are optional. If not provided, they will fall back to -implementations used by the decode/1 function:

    • for array_start: fun(_) -> [] end
    • for array_push: fun(Elem, Acc) -> [Elem | Acc] end

    • for array_finish: fun(Acc, OldAcc) -> {lists:reverse(Acc), OldAcc} end
    • for object_start: fun(_) -> [] end
    • for object_push: fun(Key, Value, Acc) -> [{Key, Value} | Acc] end

    • for object_finish: fun(Acc, OldAcc) -> {maps:from_list(Acc), OldAcc} end
    • for float: fun erlang:binary_to_float/1
    • for integer: fun erlang:binary_to_integer/1
    • for string: fun (Value) -> Value end
    • for null: the atom null

    Errors

    • error({invalid_byte, Byte}) if Binary contains unexpected byte or invalid UTF-8 byte
    • error({unexpected_sequence, Bytes}) if Binary contains invalid UTF-8 escape
    • error(unexpected_end) if Binary contains incomplete JSON value

    Example

    Decoding object keys as atoms:

    > Push = fun(Key, Value, Acc) -> [{binary_to_existing_atom(Key), Value} | Acc] end.
    -> json:decode(<<"{\"foo\": 1}">>, ok, #{object_push => Push}).
    -{#{foo => 1},ok,<<>>}
    +implementations used by the decode/1 function:

    • for array_start: fun(_) -> [] end
    • for array_push: fun(Elem, Acc) -> [Elem | Acc] end

    • for array_finish: fun(Acc, OldAcc) -> {lists:reverse(Acc), OldAcc} end
    • for object_start: fun(_) -> [] end
    • for object_push: fun(Key, Value, Acc) -> [{Key, Value} | Acc] end

    • for object_finish: fun(Acc, OldAcc) -> {maps:from_list(Acc), OldAcc} end
    • for float: fun erlang:binary_to_float/1
    • for integer: fun erlang:binary_to_integer/1
    • for string: fun (Value) -> Value end
    • for null: the atom null

    Errors

    • error({invalid_byte, Byte}) if Binary contains unexpected byte or invalid UTF-8 byte
    • error({unexpected_sequence, Bytes}) if Binary contains invalid UTF-8 escape
    • error(unexpected_end) if Binary contains incomplete JSON value

    Example

    Decoding object keys as atoms:

    > Push = fun(Key, Value, Acc) -> [{binary_to_existing_atom(Key), Value} | Acc] end.
    +> json:decode(<<"{\"foo\": 1}">>, ok, #{object_push => Push}).
    +{#{foo => 1},ok,<<>>}
    @@ -947,11 +947,11 @@

    Continue parsing a stream of bytes of a JSON value.

    Similar to decode_start/3, if the function returns {continue, State} and -there is no more data, use end_of_input instead of a binary.

    > {continue, State} = json:decode_start(<<"{\"foo\":">>, ok, #{}).
    -> json:decode_continue(<<"1}">>, State).
    -{#{foo => 1},ok,<<>>}
    > {continue, State} = json:decode_start(<<"123">>, ok, #{}).
    -> json:decode_continue(end_of_input, State).
    -{123,ok,<<>>}
    +there is no more data, use end_of_input instead of a binary.

    > {continue, State} = json:decode_start(<<"{\"foo\":">>, ok, #{}).
    +> json:decode_continue(<<"1}">>, State).
    +{#{foo => 1},ok,<<>>}
    > {continue, State} = json:decode_start(<<"123">>, ok, #{}).
    +> json:decode_continue(end_of_input, State).
    +{123,ok,<<>>}
    @@ -1015,8 +1015,8 @@ -

    Generates JSON corresponding to Term.

    Supports basic data mapping:

    ErlangJSON
    integer() | float()Number
    true | falseBoolean
    nullNull
    binary()String
    atom()String
    list()Array
    #{binary() => _}Object
    #{atom() => _}Object
    #{integer() => _}Object

    This is equivalent to encode(Term, fun json:encode_value/2).

    Examples

    > iolist_to_binary(json:encode(#{foo => <<"bar">>})).
    -<<"{\"foo\":\"bar\"}">>
    +

    Generates JSON corresponding to Term.

    Supports basic data mapping:

    ErlangJSON
    integer() | float()Number
    true | falseBoolean
    nullNull
    binary()String
    atom()String
    list()Array
    #{binary() => _}Object
    #{atom() => _}Object
    #{integer() => _}Object

    This is equivalent to encode(Term, fun json:encode_value/2).

    Examples

    > iolist_to_binary(json:encode(#{foo => <<"bar">>})).
    +<<"{\"foo\":\"bar\"}">>
    @@ -1051,11 +1051,11 @@ to be encoded and is expected to return the corresponding encoded JSON as iodata.

    Various encode_* functions in this module can be used to help in constructing such callbacks.

    Examples

    An encoder that uses a heuristic to differentiate object-like -lists of key-value pairs from plain lists:

    > encoder([{_, _} | _] = Value, Encode) -> json:encode_key_value_list(Value, Encode);
    -> encoder(Other, Encode) -> json:encode_value(Other, Encode).
    -> custom_encode(Value) -> json:encode(Value, fun(Value, Encode) -> encoder(Value, Encode) end).
    -> iolist_to_binary(custom_encode([{a, []}, {b, 1}])).
    -<<"{\"a\":[],\"b\":1}">>
    +lists of key-value pairs from plain lists:

    > encoder([{_, _} | _] = Value, Encode) -> json:encode_key_value_list(Value, Encode);
    +> encoder(Other, Encode) -> json:encode_value(Other, Encode).
    +> custom_encode(Value) -> json:encode(Value, fun(Value, Encode) -> encoder(Value, Encode) end).
    +> iolist_to_binary(custom_encode([{a, []}, {b, 1}])).
    +<<"{\"a\":[],\"b\":1}">>
    @@ -1422,11 +1422,11 @@ -

    Generates formatted JSON corresponding to Term.

    Similiar to encode/1 but with added whitespaces for formatting.

    > io:put_chars(json:format(#{foo => <<"bar">>, baz => 52})).
    -{
    +

    Generates formatted JSON corresponding to Term.

    Similiar to encode/1 but with added whitespaces for formatting.

    > io:put_chars(json:format(#{foo => <<"bar">>, baz => 52})).
    +{
       "baz": 52,
       "foo": "bar"
    -}
    +}
     ok
    @@ -1491,20 +1491,20 @@

    Generates formatted JSON corresponding to Term.

    Similar to encode/2, can be customised with the Encoder callback and Options.

    Options can include 'indent' to specify number of spaces per level and 'max' which loosely limits the width of lists.

    The Encoder will get a 'State' argument which contains the 'Options' maps merged with other data when recursing through 'Term'.

    format_value/3 or various encode_* functions in this module can be used -to help in constructing such callbacks.

    > formatter({posix_time, SysTimeSecs}, Encode, State) ->
    -    TimeStr = calendar:system_time_to_rfc3339(SysTimeSecs, [{offset, "Z"}]),
    -    json:format_value(unicode:characters_to_binary(TimeStr), Encode, State);
    -> formatter(Other, Encode, State) -> json:format_value(Other, Encode, State).
    +to help in constructing such callbacks.

    > formatter({posix_time, SysTimeSecs}, Encode, State) ->
    +    TimeStr = calendar:system_time_to_rfc3339(SysTimeSecs, [{offset, "Z"}]),
    +    json:format_value(unicode:characters_to_binary(TimeStr), Encode, State);
    +> formatter(Other, Encode, State) -> json:format_value(Other, Encode, State).
     >
    -> Fun = fun(Value, Encode, State) -> formatter(Value, Encode, State) end.
    -> Options = #{indent => 4}.
    -> Term = #{id => 1, time => {posix_time, erlang:system_time(seconds)}}.
    +> Fun = fun(Value, Encode, State) -> formatter(Value, Encode, State) end.
    +> Options = #{indent => 4}.
    +> Term = #{id => 1, time => {posix_time, erlang:system_time(seconds)}}.
     >
    -> io:put_chars(json:format(Term, Fun, Options)).
    -{
    +> io:put_chars(json:format(Term, Fun, Options)).
    +{
         "id": 1,
         "time": "2024-05-23T16:07:48Z"
    -}
    +}
     ok
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/lists.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1576)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/lists.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/lists.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -956,10 +956,10 @@

    Returns true if Pred(Elem) returns true for all elements Elem in List; -otherwise, returns false.

    Examples

    1> IsEven = fun(N) -> N rem 2 =:= 0 end.
    -2> lists:all(IsEven, [2,4,5]).
    +otherwise, returns false.

    Examples

    1> IsEven = fun(N) -> N rem 2 =:= 0 end.
    +2> lists:all(IsEven, [2,4,5]).
     false
    -3> lists:all(IsEven, [2,4,6]).
    +3> lists:all(IsEven, [2,4,6]).
     true
    @@ -989,10 +989,10 @@

    Returns true if Pred(Elem) returns true for at least one element Elem in -List; otherwise, returns false.

    Examples

    1> IsEven = fun(N) -> N rem 2 =:= 0 end.
    -2> lists:any(IsEven, [3,5,7]).
    +List; otherwise, returns false.

    Examples

    1> IsEven = fun(N) -> N rem 2 =:= 0 end.
    +2> lists:any(IsEven, [3,5,7]).
     false
    -3> lists:any(IsEven, [2,3,5,7]).
    +3> lists:any(IsEven, [2,3,5,7]).
     true
    @@ -1021,8 +1021,8 @@ -

    Returns a list in which all sublists of ListOfLists have been concatenated.

    Examples

    1> lists:append([[1, 2, 3], [a, b], [4, 5, 6]]).
    -[1,2,3,a,b,4,5,6]
    +

    Returns a list in which all sublists of ListOfLists have been concatenated.

    Examples

    1> lists:append([[1, 2, 3], [a, b], [4, 5, 6]]).
    +[1,2,3,a,b,4,5,6]
    @@ -1051,7 +1051,7 @@

    Returns a new list, List3, consisting of the elements of -List1, followed by the elements of List2.

    Examples

    1> lists:append("abc", "def").
    +List1, followed by the elements of List2.

    Examples

    1> lists:append("abc", "def").
     "abcdef"

    lists:append(A, B) is equivalent to A ++ B.

    @@ -1081,7 +1081,7 @@ -

    Concatenates the text representation of the elements of Things.

    The elements of Things can be atoms, integers, floats, or strings.

    Examples

    1> lists:concat([doc, '/', file, '.', 3]).
    +

    Concatenates the text representation of the elements of Things.

    The elements of Things can be atoms, integers, floats, or strings.

    Examples

    1> lists:concat([doc, '/', file, '.', 3]).
     "doc/file.3"
    @@ -1111,10 +1111,10 @@

    Returns a copy of List1 where the first element matching Elem is removed, if -there is such an element.

    Examples

    1> lists:delete(b, [a,b,c]).
    -[a,c]
    -2> lists:delete(x, [a,b,c]).
    -[a,b,c]
    +there is such an element.

    Examples

    1> lists:delete(b, [a,b,c]).
    +[a,c]
    +2> lists:delete(x, [a,b,c]).
    +[a,b,c]
    @@ -1145,11 +1145,11 @@

    Drops the last element of a List.

    The list must be non-empty; otherwise, the function raises a -function_clause exception.

    Examples

    1> lists:droplast([1]).
    -[]
    -2> lists:droplast([1,2,3]).
    -[1,2]
    -3> lists:droplast([]).
    +function_clause exception.

    Examples

    1> lists:droplast([1]).
    +[]
    +2> lists:droplast([1,2,3]).
    +[1,2]
    +3> lists:droplast([]).
     ** exception error: no function clause matching lists:droplast([])
    @@ -1180,10 +1180,10 @@

    Drops elements Elem from List1 while Pred(Elem) returns true, -and then returns the remaining list.

    Examples

    1> lists:dropwhile(fun is_atom/1, [a,b,c,1,2,3,x,y,z]).
    -[1,2,3,x,y,z]
    -2> lists:dropwhile(fun is_integer/1, [a,b,c,1,2,3,x,y,z]).
    -[a,b,c,1,2,3,x,y,z]
    +and then returns the remaining list.

    Examples

    1> lists:dropwhile(fun is_atom/1, [a,b,c,1,2,3,x,y,z]).
    +[1,2,3,x,y,z]
    +2> lists:dropwhile(fun is_integer/1, [a,b,c,1,2,3,x,y,z]).
    +[a,b,c,1,2,3,x,y,z]
    @@ -1211,8 +1211,8 @@ -

    Returns a list containing N copies of term Elem.

    Examples

    1> lists:duplicate(5, xx).
    -[xx,xx,xx,xx,xx]
    +

    Returns a list containing N copies of term Elem.

    Examples

    1> lists:duplicate(5, xx).
    +[xx,xx,xx,xx,xx]
    @@ -1313,14 +1313,14 @@

    Returns List1 with each element H replaced by a tuple of form {I, H}, where I is the position of H in List1.

    The enumeration starts with Index and increases by Step in each step.

    That is, enumerate/3 behaves as if it were defined as -follows:

    enumerate(I, S, List) ->
    -  {List1, _ } = lists:mapfoldl(fun(T, Acc) -> {{Acc, T}, Acc+S} end, I, List),
    -  List1.

    The default values for Index and Step are both 1.

    Examples

    1> lists:enumerate([a,b,c]).
    -[{1,a},{2,b},{3,c}]
    -2> lists:enumerate(10, [a,b,c]).
    -[{10,a},{11,b},{12,c}]
    -3> lists:enumerate(0, -2, [a,b,c]).
    -[{0,a},{-2,b},{-4,c}]
    +follows:

    enumerate(I, S, List) ->
    +  {List1, _ } = lists:mapfoldl(fun(T, Acc) -> {{Acc, T}, Acc+S} end, I, List),
    +  List1.

    The default values for Index and Step are both 1.

    Examples

    1> lists:enumerate([a,b,c]).
    +[{1,a},{2,b},{3,c}]
    +2> lists:enumerate(10, [a,b,c]).
    +[{10,a},{11,b},{12,c}]
    +3> lists:enumerate(0, -2, [a,b,c]).
    +[{0,a},{-2,b},{-4,c}]
    @@ -1350,9 +1350,9 @@

    Returns a list of elements Elem in List1 for which Pred(Elem) -returns true.

    Examples

    1> IsEven = fun(N) -> N rem 2 =:= 0 end.
    -2> lists:filter(IsEven, [1,2,3,4,5]).
    -[2,4]
    +returns true.

    Examples

    1> IsEven = fun(N) -> N rem 2 =:= 0 end.
    +2> lists:filter(IsEven, [1,2,3,4,5]).
    +[2,4]
    @@ -1391,20 +1391,20 @@

    Calls Fun(Elem) on successive elements Elem of List1 to update or remove elements from List1.

    Fun/1 must return either a Boolean or a tuple {true, Value}. The function returns the list of elements for which Fun returns a new -value, with true being equivalent to {true, Elem}.

    That is, filtermap behaves as if it were defined as follows:

    filtermap(Fun, List1) ->
    -    lists:flatmap(fun(Elem) ->
    -                          case Fun(Elem) of
    -                              false -> [];
    -                              true -> [Elem];
    -                              {true,Value} -> [Value]
    +value, with true being equivalent to {true, Elem}.

    That is, filtermap behaves as if it were defined as follows:

    filtermap(Fun, List1) ->
    +    lists:flatmap(fun(Elem) ->
    +                          case Fun(Elem) of
    +                              false -> [];
    +                              true -> [Elem];
    +                              {true,Value} -> [Value]
                               end
    -                  end, List1).

    Examples

    1> lists:filtermap(fun(X) ->
    +                  end, List1).

    Examples

    1> lists:filtermap(fun(X) ->
                                case X rem 2 of
    -                               0 -> {true, X div 2};
    +                               0 -> {true, X div 2};
                                    1 -> false
                                end
    -                   end, [1,2,3,4,5]).
    -[1,2]
    +
    end, [1,2,3,4,5]). +[1,2]
    @@ -1432,9 +1432,9 @@ -

    Equivalent to length(flatten(DeepList)), but more efficient.

    Examples

    1> lists:flatlength([a,[b,c,[d,e]],f,[[g,h,i]]]).
    +

    Equivalent to length(flatten(DeepList)), but more efficient.

    Examples

    1> lists:flatlength([a,[b,c,[d,e]],f,[[g,h,i]]]).
     9
    -2> lists:flatlength([[[]]]).
    +2> lists:flatlength([[[]]]).
     0
    @@ -1466,14 +1466,14 @@

    Takes a function from As to lists of Bs, and a list of As (List1), producing a list of Bs by applying the function to each element in List1 and /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/maps.xhtml differs (HTML document, ASCII text, with very long lines (1437)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/maps.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/maps.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -612,10 +612,10 @@

    Returns a map Map where each key-value pair from MapOrIter satisfies the predicate Pred(Key, Value).

    Unless MapOrIter is an ordered iterator returned by iterator/2, the order of the Pred(Key, Value) calls is not defined.

    The call fails with a {badmap,Map} exception if MapOrIter is not a map or -valid iterator, or with badarg if Pred is not a function of arity 2.

    Examples

    1> M = #{a => 2, b => 3, "a" => 1, "b" => 2}.
    -2> Pred = fun(K, V) -> is_atom(K) andalso V rem 2 =:= 0 end.
    -3> maps:filter(Pred, M).
    -#{a => 2}
    +valid iterator, or with badarg if Pred is not a function of arity 2.

    Examples

    1> M = #{a => 2, b => 3, "a" => 1, "b" => 2}.
    +2> Pred = fun(K, V) -> is_atom(K) andalso V rem 2 =:= 0 end.
    +3> maps:filter(Pred, M).
    +#{a => 2}
    @@ -655,12 +655,12 @@ {true, NewValue}, the value for Key is replaced with NewValue in the result map.

    Unless MapOrIter is an ordered iterator returned by iterator/2, the order of the Fun(Key, Value1) calls is not defined.

    The call fails with a {badmap,Map} exception if MapOrIter is not a map or -valid iterator, or with badarg if Fun is not a function of arity 2.

    Examples

    1> Fun = fun(K, V) when is_atom(K) -> {true, V*2};
    -            (_, V) -> V rem 2 =:= 0
    +valid iterator, or with badarg if Fun is not a function of arity 2.

    Examples

    1> Fun = fun(K, V) when is_atom(K) -> {true, V*2};
    +            (_, V) -> V rem 2 =:= 0
        end.
    -2> Map = #{k1 => 1, "k2" => 2, "k3" => 3}.
    -3> maps:filtermap(Fun, Map).
    -#{k1 => 2,"k2" => 2}
    +2>
    Map = #{k1 => 1, "k2" => 2, "k3" => 3}. +3> maps:filtermap(Fun, Map). +#{k1 => 2,"k2" => 2}
    @@ -691,10 +691,10 @@

    Returns a tuple {ok, Value}, where Value is the value associated with Key, -or error if no value is associated with Key in Map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Examples

    1> Map = #{"hi" => 42}.
    +or error if no value is associated with Key in Map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Examples

    1> Map = #{"hi" => 42}.
     2> Key = "hi".
    -3> maps:find(Key, Map).
    -{ok,42}
    +3>
    maps:find(Key, Map). +{ok,42}
    @@ -737,9 +737,9 @@ map is empty.

    Unless MapOrIter is an ordered iterator returned by iterator/2, the order of the Fun(Key, Value, AccIn) calls is not defined.

    The call fails with a {badmap,Map} exception if MapOrIter is not a map or valid iterator, or with badarg if Fun is not a function of -arity 3.

    Examples

    1> Fun = fun(K, V, AccIn) -> AccIn + V end.
    -2> Map = #{k1 => 1, k2 => 2, k3 => 3}.
    -3> maps:fold(Fun, 0, Map).
    +arity 3.

    Examples

    1> Fun = fun(K, V, AccIn) -> AccIn + V end.
    +2> Map = #{k1 => 1, k2 => 2, k3 => 3}.
    +3> maps:fold(Fun, 0, Map).
     6
    @@ -776,12 +776,12 @@

    Calls Fun(Key, Value) for every Key to Value association in MapOrIter.

    Unless MapOrIter is an ordered iterator returned by iterator/2, the order of the Fun(Key, Value) calls is not defined.

    The call fails with a {badmap,Map} exception if MapOrIter is not a map or -valid iterator, or with badarg if Fun is not a function of arity 2.

    Examples

    1> Fun = fun(K, V) -> self() ! {K,V} end.
    -2> Map = #{p => 1, q => 2,x => 10, y => 20, z => 30}.
    -3> maps:foreach(Fun, maps:iterator(Map, ordered)).
    +valid iterator, or with badarg if Fun is not a function of arity 2.

    Examples

    1> Fun = fun(K, V) -> self() ! {K,V} end.
    +2> Map = #{p => 1, q => 2,x => 10, y => 20, z => 30}.
    +3> maps:foreach(Fun, maps:iterator(Map, ordered)).
     ok
    -4> [receive X -> X end || _ <- [1,2,3,4,5]].
    -[{p,1},{q,2},{x,10},{y,20},{z,30}]
    +4>
    [receive X -> X end || _ <- [1,2,3,4,5]]. +[{p,1},{q,2},{x,10},{y,20},{z,30}]
    @@ -812,9 +812,9 @@

    Takes a list of keys and a value and builds a map where all keys are -associated with the same value.

    Examples

    1> Keys = ["a", "b", "c"].
    -2> maps:from_keys(Keys, ok).
    -#{"a" => ok,"b" => ok,"c" => ok}
    +associated with the same value.

    Examples

    1> Keys = ["a", "b", "c"].
    +2> maps:from_keys(Keys, ok).
    +#{"a" => ok,"b" => ok,"c" => ok}
    @@ -845,9 +845,9 @@

    Takes a list of key-value tuples and builds a map.

    If the same key appears more than once, the last (rightmost) value is -used, and previous values are ignored.

    Examples

    1> List = [{"a",ignored},{1337,"value two"},{42,value_three},{"a",1}].
    -2> maps:from_list(List).
    -#{42 => value_three,1337 => "value two","a" => 1}
    +used, and previous values are ignored.

    Examples

    1> List = [{"a",ignored},{1337,"value two"},{42,value_three},{"a",1}].
    +2> maps:from_list(List).
    +#{42 => value_three,1337 => "value two","a" => 1}
    @@ -879,8 +879,8 @@

    Returns value Value associated with Key if Map contains Key.

    The call fails with a {badmap,Map} exception if Map is not a map, or with a {badkey,Key} exception if no value is associated with Key.

    Examples

    1> Key = 1337.
    -2> Map = #{42 => value_two,1337 => "value one","a" => 1}.
    -3> maps:get(Key, Map).
    +2> Map = #{42 => value_two,1337 => "value one","a" => 1}.
    +3> maps:get(Key, Map).
     "value one"
    @@ -912,11 +912,11 @@

    Returns the value associated with key Key in Map, or Default if -Key is not present in the map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Examples

    1> Map = #{key1 => val1, key2 => val2}.
    -#{key1 => val1,key2 => val2}
    -2> maps:get(key1, Map, "Default value").
    +Key is not present in the map.

    The call fails with a {badmap,Map} exception if Map is not a map.

    Examples

    1> Map = #{key1 => val1, key2 => val2}.
    +#{key1 => val1,key2 => val2}
    +2> maps:get(key1, Map, "Default value").
     val1
    -3> maps:get(key3, Map, "Default value").
    +3> maps:get(key3, Map, "Default value").
     "Default value"
    @@ -956,13 +956,13 @@

    Partitions the given List into a map of groups.

    The result is a map where each key is given by KeyFun and each value is a list of elements from the given List for which KeyFun returned the same key.

    The order of elements within each group list is preserved from the original -list.

    Examples

    1> EvenOdd = fun(X) when X rem 2 =:= 0 -> even;
    -                (_) -> odd
    +list.

    Examples

    1> EvenOdd = fun(X) when X rem 2 =:= 0 -> even;
    +                (_) -> odd
                  end.
    -2> maps:groups_from_list(EvenOdd, [1, 2, 3]).
    -#{even => [2], odd => [1, 3]}
    -3> maps:groups_from_list(fun length/1, ["ant", "buffalo", "cat", "dingo"]).
    -#{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}
    +2>
    maps:groups_from_list(EvenOdd, [1, 2, 3]). +#{even => [2], odd => [1, 3]} +3> maps:groups_from_list(fun length/1, ["ant", "buffalo", "cat", "dingo"]). +#{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}
    @@ -1004,15 +1004,15 @@

    Partitions the given List into a map of groups.

    The result is a map where each key is given by KeyFun and each value is a list of elements from the given List, mapped via ValueFun, for which KeyFun returned the same key.

    The order of elements within each group list is preserved from the original -list.

    Examples

    1> EvenOdd = fun(X) -> case X rem 2 of 0 -> even; 1 -> odd end end.
    -2> Square = fun(X) -> X * X end.
    -3> maps:groups_from_list(EvenOdd, Square, [1, 2, 3]).
    -#{even => [4], odd => [1, 9]}
    -4> maps:groups_from_list(
    +list.

    Examples

    1> EvenOdd = fun(X) -> case X rem 2 of 0 -> even; 1 -> odd end end.
    +2> Square = fun(X) -> X * X end.
    +3> maps:groups_from_list(EvenOdd, Square, [1, 2, 3]).
    +#{even => [4], odd => [1, 9]}
    +4> maps:groups_from_list(
         fun length/1,
         fun lists:reverse/1,
    -    ["ant", "buffalo", "cat", "dingo"]).
    -#{3 => ["tna", "tac"],5 => ["ognid"],7 => ["olaffub"]}
    +
    ["ant", "buffalo", "cat", "dingo"]). +#{3 => ["tna", "tac"],5 => ["ognid"],7 => ["olaffub"]}
    @@ -1046,10 +1046,10 @@

    Computes the intersection of maps Map1 and Map2, producing a single map Map3.

    If a key exists in both maps, the value in Map1 is superseded by the value in Map2. Keys existing in only one of the maps are discarded -along with their values.

    The call fails with a {badmap,Map} exception if Map1 or Map2 is not a map.

    Examples

    1> Map1 = #{a => "one", b => "two"}.
    -2> Map2 = #{a => 1, c => 3}.
    -3> maps:intersect(Map1, Map2).
    -#{a => 1}
    +along with their values.

    The call fails with a {badmap,Map} exception if Map1 or Map2 is not a map.

    Examples

    1> Map1 = #{a => "one", b => "two"}.
    +2> Map2 = #{a => 1, c => 3}.
    +3> maps:intersect(Map1, Map2).
    +#{a => 1}
    @@ -1090,10 +1090,10 @@ first parameter, the value from Map1 is the second parameter, and the value from Map2 is the third parameter.

    The call fails with a {badmap,Map} exception if Map1 or Map2 is not a map. The call fails with a badarg exception if Combiner is not a fun that takes -three arguments.

    Examples

    1> Map1 = #{a => "one", b => "two"}.
    -2> Map2 = #{a => 1, c => 3}.
    -3> maps:intersect_with(fun(_Key, Val1, Val2) -> {Val1, Val2} end, Map1, Map2).
    -#{a => {"one",1}}
    +three arguments.

    Examples

    1> Map1 = #{a => "one", b => "two"}.
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/math.xhtml differs (HTML document, ASCII text, with very long lines (717))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/math.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/math.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -328,7 +328,7 @@
     
           
     
    -

    Returns the arc cosine of X in radians.

    Examples

    1> math:acos(1.0).
    +

    Returns the arc cosine of X in radians.

    Examples

    1> math:acos(1.0).
     0.0
    @@ -357,7 +357,7 @@ -

    Returns the inverse hyperbolic cosine of X.

    Examples

    1> math:acosh(1.0).
    +

    Returns the inverse hyperbolic cosine of X.

    Examples

    1> math:acosh(1.0).
     0.0
    @@ -386,7 +386,7 @@ -

    Returns the arc cosine of X in radians.

    Examples

    1> math:asin(0.0).
    +

    Returns the arc cosine of X in radians.

    Examples

    1> math:asin(0.0).
     0.0
    @@ -415,7 +415,7 @@ -

    Returns the inverse hyperbolic sine of X.

    Examples

    1> math:asinh(0.0).
    +

    Returns the inverse hyperbolic sine of X.

    Examples

    1> math:asinh(0.0).
     0.0
    @@ -445,7 +445,7 @@

    Returns the arc tangent of Y/X in radians, using the signs of both -arguments to determine the quadrant of the return value.

    Examples

    1> math:atan2(0.0, -10.0).
    +arguments to determine the quadrant of the return value.

    Examples

    1> math:atan2(0.0, -10.0).
     3.141592653589793
    @@ -474,7 +474,7 @@ -

    Returns the arc tangent of X in radians.

    Examples

    1> math:atan(0.0).
    +

    Returns the arc tangent of X in radians.

    Examples

    1> math:atan(0.0).
     0.0
    @@ -503,7 +503,7 @@ -

    Returns the inverse hyperbolic tangent of X.

    Examples

    1> math:atanh(0.0).
    +

    Returns the inverse hyperbolic tangent of X.

    Examples

    1> math:atanh(0.0).
     0.0
    @@ -534,11 +534,11 @@ -

    Returns the ceiling of X.

    Examples

    1> math:ceil(7.5).
    +

    Returns the ceiling of X.

    Examples

    1> math:ceil(7.5).
     8.0
    -2> math:ceil(-5.5).
    +2> math:ceil(-5.5).
     -5.0
    -3> math:ceil(1.0).
    +3> math:ceil(1.0).
     1.0
    @@ -567,7 +567,7 @@ -

    Returns the cosine of X in radians.

    Examples

    1> math:cos(0.0)
    +

    Returns the cosine of X in radians.

    Examples

    1> math:cos(0.0)
     1.0
    @@ -596,7 +596,7 @@ -

    Returns the hyperbolic cosine of X.

    Examples

    1> math:cosh(0.0)
    +

    Returns the hyperbolic cosine of X.

    Examples

    1> math:cosh(0.0)
     1.0
    @@ -625,9 +625,9 @@ -

    Returns the error function of X.

    See Error function (Wikipedia).

    Examples

    1> math:erf(0.0).
    +

    Returns the error function of X.

    See Error function (Wikipedia).

    Examples

    1> math:erf(0.0).
     0.0
    -2> math:erf(10.0).
    +2> math:erf(10.0).
     1.0
    @@ -657,7 +657,7 @@

    Returns 1.0 - erf(X), computed using methods -that avoid cancellation for large X.

    Examples

    1> math:erfc(0.0).
    +that avoid cancellation for large X.

    Examples

    1> math:erfc(0.0).
     1.0
    @@ -686,9 +686,9 @@ -

    Returns e raised to the power of X.

    Examples

    1> math:exp(0).
    +

    Returns e raised to the power of X.

    Examples

    1> math:exp(0).
     1.0
    -2> trunc(100 * math:exp(1)).
    +2> trunc(100 * math:exp(1)).
     271
    @@ -719,11 +719,11 @@ -

    Returns the floor of X.

    Examples

    1> math:floor(9.1).
    +

    Returns the floor of X.

    Examples

    1> math:floor(9.1).
     9.0
    -2> math:floor(-1.5).
    +2> math:floor(-1.5).
     -2.0
    -3> math:floor(1.0)
    +3> math:floor(1.0)
     1.0
    @@ -754,7 +754,7 @@ -

    Returns the floating point remainder X divided by Y.

    Examples

    1> math:fmod(10.5, 8.0).
    +

    Returns the floating point remainder X divided by Y.

    Examples

    1> math:fmod(10.5, 8.0).
     2.5
    @@ -785,11 +785,11 @@ -

    Returns logarithm of X to base 2.

    Examples

    1> math:log2(1.0).
    +

    Returns logarithm of X to base 2.

    Examples

    1> math:log2(1.0).
     0.0
    -2> math:log2(2.0).
    +2> math:log2(2.0).
     1.0
    -3> math:log2(64).
    +3> math:log2(64).
     6.0
    @@ -818,11 +818,11 @@ -

    Returns logarithm of X to base 10.

    Examples

    1> math:log10(1.0).
    +

    Returns logarithm of X to base 10.

    Examples

    1> math:log10(1.0).
     0.0
    -2> math:log10(10.0).
    +2> math:log10(10.0).
     1.0
    -3> math:log10(100).
    +3> math:log10(100).
     2.0
    @@ -851,9 +851,9 @@ -

    Returns the natural logarithm of X.

    Examples

    1> math:log(1.0).
    +

    Returns the natural logarithm of X.

    Examples

    1> math:log(1.0).
     0.0
    -2> math:log(2.718281828459045).
    +2> math:log(2.718281828459045).
     1.0
    @@ -882,7 +882,7 @@ /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/ms_transform.xhtml differs (HTML document, ASCII text, with very long lines (2060)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/ms_transform.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/ms_transform.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -42,31 +42,31 @@ table and construct a list of tuples containing relevant parts of the data in these rows. One can use ets:foldl/3 instead, but the ets:select/2 call is far more efficient. Without the translation provided by ms_transform, one must -struggle with writing match specifications terms to accommodate this.

    Consider a simple table of employees:

    -record(emp, {empno,     %Employee number as a string, the key
    +struggle with writing match specifications terms to accommodate this.

    Consider a simple table of employees:

    -record(emp, {empno,     %Employee number as a string, the key
                   surname,   %Surname of the employee
                   givenname, %Given name of employee
                   dept,      %Department, one of {dev,sales,prod,adm}
    -              empyear}). %Year the employee was employed

    We create the table using:

    ets:new(emp_tab, [{keypos,#emp.empno},named_table,ordered_set]).

    We fill the table with randomly chosen data:

    [{emp,"011103","Black","Alfred",sales,2000},
    - {emp,"041231","Doe","John",prod,2001},
    - {emp,"052341","Smith","John",dev,1997},
    - {emp,"076324","Smith","Ella",sales,1995},
    - {emp,"122334","Weston","Anna",prod,2002},
    - {emp,"535216","Chalker","Samuel",adm,1998},
    - {emp,"789789","Harrysson","Joe",adm,1996},
    - {emp,"963721","Scott","Juliana",dev,2003},
    - {emp,"989891","Brown","Gabriel",prod,1999}]

    Assuming that we want the employee numbers of everyone in the sales department, -there are several ways.

    ets:match/2 can be used:

    1> ets:match(emp_tab, {'_', '$1', '_', '_', sales, '_'}).
    -[["011103"],["076324"]]

    ets:match/2 uses a simpler type of match specification, but it is still + empyear}). %Year the employee was employed

    We create the table using:

    ets:new(emp_tab, [{keypos,#emp.empno},named_table,ordered_set]).

    We fill the table with randomly chosen data:

    [{emp,"011103","Black","Alfred",sales,2000},
    + {emp,"041231","Doe","John",prod,2001},
    + {emp,"052341","Smith","John",dev,1997},
    + {emp,"076324","Smith","Ella",sales,1995},
    + {emp,"122334","Weston","Anna",prod,2002},
    + {emp,"535216","Chalker","Samuel",adm,1998},
    + {emp,"789789","Harrysson","Joe",adm,1996},
    + {emp,"963721","Scott","Juliana",dev,2003},
    + {emp,"989891","Brown","Gabriel",prod,1999}]

    Assuming that we want the employee numbers of everyone in the sales department, +there are several ways.

    ets:match/2 can be used:

    1> ets:match(emp_tab, {'_', '$1', '_', '_', sales, '_'}).
    +[["011103"],["076324"]]

    ets:match/2 uses a simpler type of match specification, but it is still unreadable, and one has little control over the returned result. It is always a -list of lists.

    ets:foldl/3 or ets:foldr/3 can be used to avoid the nested lists:

    ets:foldr(fun(#emp{empno = E, dept = sales},Acc) -> [E | Acc];
    -             (_,Acc) -> Acc
    +list of lists.

    ets:foldl/3 or ets:foldr/3 can be used to avoid the nested lists:

    ets:foldr(fun(#emp{empno = E, dept = sales},Acc) -> [E | Acc];
    +             (_,Acc) -> Acc
               end,
    -          [],
    -          emp_tab).

    The result is ["011103","076324"]. The fun is straightforward, so the only + [], + emp_tab).

    The result is ["011103","076324"]. The fun is straightforward, so the only problem is that all the data from the table must be transferred from the table to the calling process for filtering. That is inefficient compared to the ets:match/2 call where the filtering can be done "inside" the emulator and -only the result is transferred to the process.

    Consider a "pure" ets:select/2 call that does what ets:foldr does:

    ets:select(emp_tab, [{#emp{empno = '$1', dept = sales, _='_'},[],['$1']}]).

    Although the record syntax is used, it is still hard to read and even harder to +only the result is transferred to the process.

    Consider a "pure" ets:select/2 call that does what ets:foldr does:

    ets:select(emp_tab, [{#emp{empno = '$1', dept = sales, _='_'},[],['$1']}]).

    Although the record syntax is used, it is still hard to read and even harder to write. The first element of the tuple, #emp{empno = '$1', dept = sales, _='_'}, tells what to match. Elements not matching this are not returned, as in the ets:match/2 example. The second @@ -77,12 +77,12 @@ hence the employee number is returned. The result is ["011103","076324"], as in the ets:foldr/3 example, but the result is retrieved much more efficiently in terms of execution speed and memory consumption.

    Using ets:fun2ms/1, we can combine the ease of use of the ets:foldr/3 and -the efficiency of the pure ets:select/2 example:

    -include_lib("stdlib/include/ms_transform.hrl").
    +the efficiency of the pure ets:select/2 example:

    -include_lib("stdlib/include/ms_transform.hrl").
     
    -ets:select(emp_tab, ets:fun2ms(
    -                      fun(#emp{empno = E, dept = sales}) ->
    +ets:select(emp_tab, ets:fun2ms(
    +                      fun(#emp{empno = E, dept = sales}) ->
                                   E
    -                      end)).

    This example requires no special knowledge of match specifications to + end)).

    This example requires no special knowledge of match specifications to understand. The head of the fun matches what you want to filter out and the body returns what you want returned. As long as the fun can be kept within the limits of the match specifications, there is no need to transfer all table data to the @@ -98,28 +98,28 @@ specifications by hand.

    Example 2

    Assume that we want to get all the employee numbers of employees hired before year 2000. Using ets:match/2 is not an alternative here, as relational operators cannot be expressed there. Once again, ets:foldr/3 can do it -(slowly, but correct):

    ets:foldr(fun(#emp{empno = E, empyear = Y},Acc) when Y < 2000 -> [E | Acc];
    -                  (_,Acc) -> Acc
    +(slowly, but correct):

    ets:foldr(fun(#emp{empno = E, empyear = Y},Acc) when Y < 2000 -> [E | Acc];
    +                  (_,Acc) -> Acc
               end,
    -          [],
    -          emp_tab).

    The result is ["052341","076324","535216","789789","989891"], as expected. The + [], + emp_tab).

    The result is ["052341","076324","535216","789789","989891"], as expected. The equivalent expression using a handwritten match specification would look like -this:

    ets:select(emp_tab, [{#emp{empno = '$1', empyear = '$2', _='_'},
    -                     [{'<', '$2', 2000}],
    -                     ['$1']}]).

    This gives the same result. [{'<', '$2', 2000}] is in the guard part and +this:

    ets:select(emp_tab, [{#emp{empno = '$1', empyear = '$2', _='_'},
    +                     [{'<', '$2', 2000}],
    +                     ['$1']}]).

    This gives the same result. [{'<', '$2', 2000}] is in the guard part and therefore discards anything that does not have an empyear (bound to '$2' in -the head) less than 2000, as the guard in the foldr/3 example.

    We write it using ets:fun2ms/1:

    -include_lib("stdlib/include/ms_transform.hrl").
    +the head) less than 2000, as the guard in the foldr/3 example.

    We write it using ets:fun2ms/1:

    -include_lib("stdlib/include/ms_transform.hrl").
     
    -ets:select(emp_tab, ets:fun2ms(
    -                      fun(#emp{empno = E, empyear = Y}) when Y < 2000 ->
    +ets:select(emp_tab, ets:fun2ms(
    +                      fun(#emp{empno = E, empyear = Y}) when Y < 2000 ->
                                E
    -                      end)).

    Example 3

    Assume that we want the whole object matching instead of only one element. One + end)).

    Example 3

    Assume that we want the whole object matching instead of only one element. One alternative is to assign a variable to every part of the record and build it up -once again in the body of the fun, but the following is easier:

    ets:select(emp_tab, ets:fun2ms(
    -                      fun(Obj = #emp{empno = E, empyear = Y})
    +once again in the body of the fun, but the following is easier:

    ets:select(emp_tab, ets:fun2ms(
    +                      fun(Obj = #emp{empno = E, empyear = Y})
                              when Y < 2000 ->
                                   Obj
    -                      end)).

    As in ordinary Erlang matching, you can bind a variable to the whole matched + end)).

    As in ordinary Erlang matching, you can bind a variable to the whole matched object using a "match inside the match", that is, a =. Unfortunately in funs translated to match specifications, it is allowed only at the "top-level", that is, matching the whole object arriving to be matched into a separate variable. @@ -128,34 +128,34 @@ object/0 also returns the whole matched object, see section Warnings and Restrictions.

    Example 4

    This example concerns the body of the fun. Assume that all employee numbers beginning with zero (0) must be changed to begin with one (1) instead, and -that we want to create the list [{<Old empno>,<New empno>}]:

    ets:select(emp_tab, ets:fun2ms(
    -                      fun(#emp{empno = [$0 | Rest] }) ->
    -                              {[$0|Rest],[$1|Rest]}
    -                      end)).

    This query hits the feature of partially bound keys in table type ordered_set, +that we want to create the list [{<Old empno>,<New empno>}]:

    ets:select(emp_tab, ets:fun2ms(
    +                      fun(#emp{empno = [$0 | Rest] }) ->
    +                              {[$0|Rest],[$1|Rest]}
    +                      end)).

    This query hits the feature of partially bound keys in table type ordered_set, so that not the whole table needs to be searched, only the part containing keys beginning with 0 is looked into.

    Example 5

    The fun can have many clauses. Assume that we want to do the following:

    • If an employee started before 1997, return the tuple {inventory, <employee number>}.
    • If an employee started 1997 or later, but before 2001, return {rookie, <employee number>}.
    • For all other employees, return {newbie, <employee number>}, except for those named Smith as they would be affronted by anything other than the tag guru and that is also what is returned for their numbers: -{guru, <employee number>}.

    This is accomplished as follows:

    ets:select(emp_tab, ets:fun2ms(
    -                      fun(#emp{empno = E, surname = "Smith" }) ->
    -                              {guru,E};
    -                         (#emp{empno = E, empyear = Y}) when Y < 1997  ->
    -                              {inventory, E};
    -                         (#emp{empno = E, empyear = Y}) when Y > 2001  ->
    -                              {newbie, E};
    -                         (#emp{empno = E, empyear = Y}) -> % 1997 -- 2001
    -                              {rookie, E}
    -                      end)).

    The result is as follows:

    [{rookie,"011103"},
    - {rookie,"041231"},
    - {guru,"052341"},
    - {guru,"076324"},
    - {newbie,"122334"},
    - {rookie,"535216"},
    - {inventory,"789789"},
    - {newbie,"963721"},
    - {rookie,"989891"}]

    Useful BIFs

    What more can you do? A simple answer is: see the documentation of +{guru, <employee number>}.

    This is accomplished as follows:

    ets:select(emp_tab, ets:fun2ms(
    +                      fun(#emp{empno = E, surname = "Smith" }) ->
    +                              {guru,E};
    +                         (#emp{empno = E, empyear = Y}) when Y < 1997  ->
    +                              {inventory, E};
    +                         (#emp{empno = E, empyear = Y}) when Y > 2001  ->
    +                              {newbie, E};
    +                         (#emp{empno = E, empyear = Y}) -> % 1997 -- 2001
    +                              {rookie, E}
    +                      end)).

    The result is as follows:

    [{rookie,"011103"},
    + {rookie,"041231"},
    + {guru,"052341"},
    + {guru,"076324"},
    + {newbie,"122334"},
    + {rookie,"535216"},
    + {inventory,"789789"},
    + {newbie,"963721"},
    + {rookie,"989891"}]

    Useful BIFs

    What more can you do? A simple answer is: see the documentation of match specifications in ERTS User's Guide. However, the following is a brief overview of the most useful "built-in functions" that you can use when the fun is to be translated into a match specification by @@ -190,18 +190,18 @@ more, as filtering using Erlang code is not a good idea when tracing (except afterwards, if you trace to file). The concept is similar to that of ets:fun2ms/1 except that you usually use it directly from the shell (which can -also be done with ets:fun2ms/1).

    The following is an example module to trace on:

    -module(toy).
    +also be done with ets:fun2ms/1).

    The following is an example module to trace on:

    -module(toy).
     
    --export([start/1, store/2, retrieve/1]).
    +-export([start/1, store/2, retrieve/1]).
     
    -start(Args) ->
    -    toy_table = ets:new(toy_table, Args).
    +start(Args) ->
    +    toy_table = ets:new(toy_table, Args).
     
    -store(Key, Value) ->
    -    ets:insert(toy_table, {Key,Value}).
    +store(Key, Value) ->
    +    ets:insert(toy_table, {Key,Value}).
     
    -retrieve(Key) ->
    -    [{Key, Value}] = ets:lookup(toy_table, Key),
    +retrieve(Key) ->
    +    [{Key, Value}] = ets:lookup(toy_table, Key),
         Value.

    During model testing, the first test results in {badmatch,16} in {toy,start,1}, why?

    We suspect the ets:new/2 call, as we match hard on the return value, but want only the particular new/2 call with toy_table as first parameter. So we @@ -210,32 +210,32 @@ trace pattern, so there is no need to call trace only a few processes (usually it is not):

    2> dbg:p(all,call).
     {ok,[{matched,nonode@nohost,25}]}

    We specify the filter, we want to view calls that resemble -ets:new(toy_table, <something>):

    3> dbg:tp(ets,new,dbg:fun2ms(fun([toy_table,_]) -> true end)).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/notes.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (10265))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/notes.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/notes.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -17,49 +17,49 @@
       
     
         

    STDLIB Release Notes

    -

    This document describes the changes made to the STDLIB application.

    STDLIB 7.3.0.1

    Fixed Bugs and Malfunctions

    • Fixed a bug where zip:unzip/1,2 and zip:extract/1,2 were vulnerable to a relative path traversal attack. A crafted zip archive containing entry names such as ../x/y could have caused files to be written outside the intended extraction directory.

      Thanks to Jonatan Männchen and Zhang Delong for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

      Own Id: OTP-20143 Aux Id: CVE-2026-47078, PR-11386

    STDLIB 7.3

    Fixed Bugs and Malfunctions

    • Fixed functions ets:init_table/2, ets:tab2file/2,3, ets:table/1,2, ets:i/0,1, dets:from_ets/2, and dets:to_ets/2 to resolve named table arguments only once. This will prevent strange effects if the named table is deleted and recreated by a concurrent process.

      Own Id: OTP-19911 Aux Id: PR-10536

    • Corrected the af_zip_generator() type in the parser and syntax_tools.

      Own Id: OTP-19939

    • For a function that started with a bracket-only pattern (such as []), the ?FUNCTION_ARITY macro would evaluate to one less than the actual arity.

      Own Id: OTP-19988 Aux Id: GH-10705, PR-10708

    Improvements and New Features

    • Added support for zstd compression in the file module.

      Own Id: OTP-19860 Aux Id: PR-10385

    • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

      A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

      make release_docs places the documentation in the released code under the doc folder.

      make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

      The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

      Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

      Improves the source Software-Bill-of-Materials

      • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
      • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
      • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

      Own Id: OTP-19886 Aux Id: PR-10434

    • The removal of the slave and slave modules have been postponed to Erlang/OTP 31.

      The partial removal of the archive feature has been postponed to Erlang/OTP 30.

      Own Id: OTP-19989 Aux Id: PR-10714

    STDLIB 7.2.1

    Fixed Bugs and Malfunctions

    • Fixed bug in ets:update_counter/4 and ets:update_element/4 accepting and inserting a default tuple smaller than the keypos of the table. Such a tuple without a key element would make the table internally inconsistent and might lead to bad behavior at table access, like ERTS runtime crash.

      Now a call to ets:update_counter/4 or ets:update_element/4 will fail with badarg if the key does not exist in the table and the default tuple is too small.

      Own Id: OTP-19962 Aux Id: PR-10616

    STDLIB 7.2

    Fixed Bugs and Malfunctions

    • When creating a tar archive using erl_tar, leading slashes would be kept for filenames with up to 100 characters. The slash would be dropped for longer filenames. This has been corrected to always keep the leading slash.

      Own Id: OTP-19066 Aux Id: PR-8309

    • For some function heads or case expressions with a huge number of clauses, the compiler could spend an inordinate amount of time compiling the code.

      Own Id: OTP-19797 Aux Id: PR-10252

    • Passing a type for a fun as a macro argument would result in a "badly formed argument" error message from the compiler. Example:

      -module(test).
      --define(FOO(X), X).
      --type foo() :: ?FOO(fun(() -> ok)).

      Compiling this module would result in the following error message:

      test.erl:3:17: badly formed argument for macro 'FOO'
      +

      This document describes the changes made to the STDLIB application.

      STDLIB 7.3.0.1

      Fixed Bugs and Malfunctions

      • Fixed a bug where zip:unzip/1,2 and zip:extract/1,2 were vulnerable to a relative path traversal attack. A crafted zip archive containing entry names such as ../x/y could have caused files to be written outside the intended extraction directory.

        Thanks to Jonatan Männchen and Zhang Delong for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

        Own Id: OTP-20143 Aux Id: CVE-2026-47078, PR-11386

      STDLIB 7.3

      Fixed Bugs and Malfunctions

      • Fixed functions ets:init_table/2, ets:tab2file/2,3, ets:table/1,2, ets:i/0,1, dets:from_ets/2, and dets:to_ets/2 to resolve named table arguments only once. This will prevent strange effects if the named table is deleted and recreated by a concurrent process.

        Own Id: OTP-19911 Aux Id: PR-10536

      • Corrected the af_zip_generator() type in the parser and syntax_tools.

        Own Id: OTP-19939

      • For a function that started with a bracket-only pattern (such as []), the ?FUNCTION_ARITY macro would evaluate to one less than the actual arity.

        Own Id: OTP-19988 Aux Id: GH-10705, PR-10708

      Improvements and New Features

      • Added support for zstd compression in the file module.

        Own Id: OTP-19860 Aux Id: PR-10385

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      • The removal of the slave and slave modules have been postponed to Erlang/OTP 31.

        The partial removal of the archive feature has been postponed to Erlang/OTP 30.

        Own Id: OTP-19989 Aux Id: PR-10714

      STDLIB 7.2.1

      Fixed Bugs and Malfunctions

      • Fixed bug in ets:update_counter/4 and ets:update_element/4 accepting and inserting a default tuple smaller than the keypos of the table. Such a tuple without a key element would make the table internally inconsistent and might lead to bad behavior at table access, like ERTS runtime crash.

        Now a call to ets:update_counter/4 or ets:update_element/4 will fail with badarg if the key does not exist in the table and the default tuple is too small.

        Own Id: OTP-19962 Aux Id: PR-10616

      STDLIB 7.2

      Fixed Bugs and Malfunctions

      • When creating a tar archive using erl_tar, leading slashes would be kept for filenames with up to 100 characters. The slash would be dropped for longer filenames. This has been corrected to always keep the leading slash.

        Own Id: OTP-19066 Aux Id: PR-8309

      • For some function heads or case expressions with a huge number of clauses, the compiler could spend an inordinate amount of time compiling the code.

        Own Id: OTP-19797 Aux Id: PR-10252

      • Passing a type for a fun as a macro argument would result in a "badly formed argument" error message from the compiler. Example:

        -module(test).
        +-define(FOO(X), X).
        +-type foo() :: ?FOO(fun(() -> ok)).

        Compiling this module would result in the following error message:

        test.erl:3:17: badly formed argument for macro 'FOO'
         %    5| -type foo() :: ?FOO(fun(() -> ok)).
        -%

        Own Id: OTP-19821 Aux Id: GH-10280, PR-10309

      • Fixed an issue that prohibited the use of user defined functions within a restricted shell.

        Own Id: OTP-19833 Aux Id: PR-10315

      • The deprecated function crypto:rand_uniform/2 has gotten a new replacement function crypto:strong_rand_range/1. When implementing this the documentation of crypto and rand has been rewritten a bit and improved.

        Own Id: OTP-19841 Aux Id: PR-10344

      • Fixed a bug in the shell where a reference to a locally defined function would cause a crash.

        Own Id: OTP-19850 Aux Id: GH-10294

      Improvements and New Features

      • You are now able to read the reference manual with man.

        Own Id: OTP-19787 Aux Id: PR-10237

      • Improved spec for ets:lookup_element/4.

        Own Id: OTP-19798 Aux Id: PR-10236

      • The mnesia_registry module will be removed in Erlang/OTP 29.

        Own Id: OTP-19808 Aux Id: PR-10275

      STDLIB 7.1

      Fixed Bugs and Malfunctions

      • The save_module/1 command in the shell now saves both the locally defined records and the imported records using the rr/1 command.

        Own Id: OTP-19647 Aux Id: GH-9816, PR-9897

      • It's now possible to write lists:map(fun is_atom/1, []) or lists:map(fun my_func/1, []) in the shell, instead of lists:map(fun erlang:is_atom/1, []) or lists:map(fun shell_default:my_func/1, []).

        Own Id: OTP-19649 Aux Id: GH-9771, PR-9898

      • The shell no longer crashes when requesting to auto-complete map keys containing non-atoms.

        Own Id: OTP-19659 Aux Id: PR-9896

      • A remote shell can now exit by closing the input stream, without terminating the remote node.

        Own Id: OTP-19667 Aux Id: PR-9912

      • Fixed guard check for is_record/2 in the linter.

        Own Id: OTP-19704 Aux Id: GH-10020, PR-10034

      Improvements and New Features

      • Added a flag option shell_hints and function shell:hints/1. You can now disable the warning in the shell when a command is taking longer than 5 seconds.

        Own Id: OTP-19759 Aux Id: PR-10121

      STDLIB 7.0.3

      Fixed Bugs and Malfunctions

      • Update PCRE2 from 10.45 to 10.46. Fixes potential buffer read overflow on regular expressions with (*scs:) and (*ACCEPT) syntax combined.

        Own Id: OTP-19755 Aux Id: CVE-2025-58050

      STDLIB 7.0.2

      Fixed Bugs and Malfunctions

      • A set of small bugs in sort stability for `lists:sort/1` and `lists:keysort/1` has been fixed. The bug happened for only some, seemingly random, element sequences. Most sorts were stable.

        Sort stability for `lists:sort/1` is only possible to observe when sorting lists with floating point and integer numbers of the same value.

        For `lists:keysort/1` the list had to start with two tuples where the keys or the whole tuples compared equal.

        Own Id: OTP-19673 Aux Id: ERIERL-1240

      • Fixed bug in io_lib:bformat/2 which crashed if format string contained unicode characters.

        Own Id: OTP-19680 Aux Id: PR-9952

      STDLIB 7.0.1

      Fixed Bugs and Malfunctions

      • Properly strip the leading / and drive letter from filepaths when zipping and unzipping archives.

        Thanks to Wander Nauta for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

        Own Id: OTP-19653 Aux Id: CVE-2025-4748, PR-9941

      STDLIB 7.0

      Fixed Bugs and Malfunctions

      • Shell help now orders the commands in alphabetical order.

        Own Id: OTP-19161 Aux Id: PR-8573

      • proc_lib:stop/1,3 (and in extension gen_server:stop/3, gen_statem:stop/3 and so on) have been updated to not throw an error if the process to be stopped exits with the same reason as given to proc_lib:stop/3.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19233 Aux Id: PR-8772

      • The size of an atom in the Erlang source code was limited to 255 bytes in previous releases, meaning that an atom containing only emojis could contain only 63 emojis.

        While atoms are still only allowed to contain 255 characters, the number of bytes is no longer limited.

        External tools that parse the AtU8 chunk of a BEAM file directly need to be updated. Tools that use beam_lib:chunks(Beam, [atoms]) to read the atom table will continue to work.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19285 Aux Id: PR-8913

      • argparse:help/1 now accepts unicode:chardata/0.

        Own Id: OTP-19303 Aux Id: PR-8932

      • The literals chunk in BEAM is no longer compressed, resulting in slightly smaller BEAM files when a BEAM file is stripped using beam_lib:strip_files/1.

        This is a potential incompatibility for tools that read and interpret the contents of the literal chunk. One way to update such tools to work with the new format is to retrieve the chunk using beam_lib:chunks(Beam, [literals]).

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19323 Aux Id: GH-8967, PR-8988

      • The previous digraph_utils:preorder/1 and digraph_utils:postorder/1 did not start the traversal from root nodes. This fix makes both traversals only start or restart from a root node in one of the components, or an arbitrary node if no root node can be visited.

        Own Id: OTP-19393 Aux Id: PR-9171

      • Auto-completion in the shell is now significantly faster for function parameters that uses complex custom types.

        Own Id: OTP-19413 Aux Id: PR-9271

      • Stringfying a non-latin1 atom will now produce a readable string instead of encoding each character using \x{...} escape sequences. Example:

        -define(S(T), ??T).
        +%

        Own Id: OTP-19821 Aux Id: GH-10280, PR-10309

      • Fixed an issue that prohibited the use of user defined functions within a restricted shell.

        Own Id: OTP-19833 Aux Id: PR-10315

      • The deprecated function crypto:rand_uniform/2 has gotten a new replacement function crypto:strong_rand_range/1. When implementing this the documentation of crypto and rand has been rewritten a bit and improved.

        Own Id: OTP-19841 Aux Id: PR-10344

      • Fixed a bug in the shell where a reference to a locally defined function would cause a crash.

        Own Id: OTP-19850 Aux Id: GH-10294

      Improvements and New Features

      • You are now able to read the reference manual with man.

        Own Id: OTP-19787 Aux Id: PR-10237

      • Improved spec for ets:lookup_element/4.

        Own Id: OTP-19798 Aux Id: PR-10236

      • The mnesia_registry module will be removed in Erlang/OTP 29.

        Own Id: OTP-19808 Aux Id: PR-10275

      STDLIB 7.1

      Fixed Bugs and Malfunctions

      • The save_module/1 command in the shell now saves both the locally defined records and the imported records using the rr/1 command.

        Own Id: OTP-19647 Aux Id: GH-9816, PR-9897

      • It's now possible to write lists:map(fun is_atom/1, []) or lists:map(fun my_func/1, []) in the shell, instead of lists:map(fun erlang:is_atom/1, []) or lists:map(fun shell_default:my_func/1, []).

        Own Id: OTP-19649 Aux Id: GH-9771, PR-9898

      • The shell no longer crashes when requesting to auto-complete map keys containing non-atoms.

        Own Id: OTP-19659 Aux Id: PR-9896

      • A remote shell can now exit by closing the input stream, without terminating the remote node.

        Own Id: OTP-19667 Aux Id: PR-9912

      • Fixed guard check for is_record/2 in the linter.

        Own Id: OTP-19704 Aux Id: GH-10020, PR-10034

      Improvements and New Features

      • Added a flag option shell_hints and function shell:hints/1. You can now disable the warning in the shell when a command is taking longer than 5 seconds.

        Own Id: OTP-19759 Aux Id: PR-10121

      STDLIB 7.0.3

      Fixed Bugs and Malfunctions

      • Update PCRE2 from 10.45 to 10.46. Fixes potential buffer read overflow on regular expressions with (*scs:) and (*ACCEPT) syntax combined.

        Own Id: OTP-19755 Aux Id: CVE-2025-58050

      STDLIB 7.0.2

      Fixed Bugs and Malfunctions

      • A set of small bugs in sort stability for `lists:sort/1` and `lists:keysort/1` has been fixed. The bug happened for only some, seemingly random, element sequences. Most sorts were stable.

        Sort stability for `lists:sort/1` is only possible to observe when sorting lists with floating point and integer numbers of the same value.

        For `lists:keysort/1` the list had to start with two tuples where the keys or the whole tuples compared equal.

        Own Id: OTP-19673 Aux Id: ERIERL-1240

      • Fixed bug in io_lib:bformat/2 which crashed if format string contained unicode characters.

        Own Id: OTP-19680 Aux Id: PR-9952

      STDLIB 7.0.1

      Fixed Bugs and Malfunctions

      • Properly strip the leading / and drive letter from filepaths when zipping and unzipping archives.

        Thanks to Wander Nauta for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

        Own Id: OTP-19653 Aux Id: CVE-2025-4748, PR-9941

      STDLIB 7.0

      Fixed Bugs and Malfunctions

      • Shell help now orders the commands in alphabetical order.

        Own Id: OTP-19161 Aux Id: PR-8573

      • proc_lib:stop/1,3 (and in extension gen_server:stop/3, gen_statem:stop/3 and so on) have been updated to not throw an error if the process to be stopped exits with the same reason as given to proc_lib:stop/3.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19233 Aux Id: PR-8772

      • The size of an atom in the Erlang source code was limited to 255 bytes in previous releases, meaning that an atom containing only emojis could contain only 63 emojis.

        While atoms are still only allowed to contain 255 characters, the number of bytes is no longer limited.

        External tools that parse the AtU8 chunk of a BEAM file directly need to be updated. Tools that use beam_lib:chunks(Beam, [atoms]) to read the atom table will continue to work.

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19285 Aux Id: PR-8913

      • argparse:help/1 now accepts unicode:chardata/0.

        Own Id: OTP-19303 Aux Id: PR-8932

      • The literals chunk in BEAM is no longer compressed, resulting in slightly smaller BEAM files when a BEAM file is stripped using beam_lib:strip_files/1.

        This is a potential incompatibility for tools that read and interpret the contents of the literal chunk. One way to update such tools to work with the new format is to retrieve the chunk using beam_lib:chunks(Beam, [literals]).

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-19323 Aux Id: GH-8967, PR-8988

      • The previous digraph_utils:preorder/1 and digraph_utils:postorder/1 did not start the traversal from root nodes. This fix makes both traversals only start or restart from a root node in one of the components, or an arbitrary node if no root node can be visited.

        Own Id: OTP-19393 Aux Id: PR-9171

      • Auto-completion in the shell is now significantly faster for function parameters that uses complex custom types.

        Own Id: OTP-19413 Aux Id: PR-9271

      • Stringfying a non-latin1 atom will now produce a readable string instead of encoding each character using \x{...} escape sequences. Example:

        -define(S(T), ??T).
         
        -atom() ->
        -    ?S('атом').

        The atom/0 function now returns "'атом'" instead of "'\\x{430}\\x{442}\\x{43E}\\x{43C}'".

        Own Id: OTP-19421 Aux Id: GH-9173, PR-9276

      • A few minor issues were corrected in m:syntax_tools, as well in the erl_anno module.

        Own Id: OTP-19422 Aux Id: PR-9253

      • dets could print error messages to standard output when repairing DETS files. This has been changed to send the messages to logger.

        ets:fun2ms would print an error message to standard output as well as returning an error tuple. The printing of the message has been removed.

        Own Id: OTP-19427 Aux Id: PR-9232, PR-9446

      • The functions for converting to and from the RFC1339 date and time format would not properly handle fractional seconds for negative times.

        Own Id: OTP-19441 Aux Id: GH-9279, PR-9280

      • Replaced calls to deprecated crypto:start() with application:start(crypto).

        Own Id: OTP-19485 Aux Id: PR-8592

      • Fixed a bug when calling shell completion on a reserved word followed by a ( would crash the shell.

        Own Id: OTP-19511 Aux Id: GH-9470

      • Corrected the spec of ets:update_element/4.

        Own Id: OTP-19514 Aux Id: PR-9504

      • Corrected the spec for ets:info/1.

        Own Id: OTP-19515 Aux Id: PR-9514

      • Fixed crash when defining records with a string field in the shell

        Own Id: OTP-19533 Aux Id: GH-9557

      • Details in the hibernation implementation and time-out handling has been improved for gen_statem. In particular to avoid selective receive when cancelling a time-out.

        Own Id: OTP-19540 Aux Id: PR-9579

      • Fixed a bug when getting help on a module compiled without debug_info.

        Own Id: OTP-19583 Aux Id: PR-9654

      • Fix zip extraction to wrap invalid DOS timestamps to their correct value instead of returning the actual value. Before this fix the timestamp returned could have a second greater than 59. The bug has been present since Erlang/OTP 27.1.

        Own Id: OTP-19593 Aux Id: PR-9537, GH-9536

      • Enhance specs of timeout for improving documentation and dialyzer analysis.

        Own Id: OTP-19604 Aux Id: PR-9574

      Improvements and New Features

      • Singleton type variables in an union type do not make sense from Dialyzer's point of view. The following example is ill-typed:

        -spec run_test(Opts) -> term()
        -      when Opts :: {join_specs, Bool} | {test, Bool}.

        This used to be reported as a warning. In OTP-28, this is an error

        Own Id: OTP-19125 Aux Id: PR-8556

      • By default, sets created by the sets module will now be represented as maps.

        Own Id: OTP-19127 Aux Id: PR-8429

      • For various error types, the compiler now tries to suggest potential fixes by adding "did you mean ...?" at the end of error messages.

        When a function is used with wrong arity, the compiler will try to suggest a defined function with the same name but a different arity. For example, given the following module:

        -module(typos).
        --export([t/0]).
        -bar(A) -> A.
        -bar(A,A,A) -> A.
        -bar(A,A,A,A) -> A.
        -t() -> bar(0, 0).

        The compiler will emit the following message:

        typo.erl:6:12: function bar/2 undefined, did you mean bar/1,3,4?
        +atom() ->
        +    ?S('атом').

        The atom/0 function now returns "'атом'" instead of "'\\x{430}\\x{442}\\x{43E}\\x{43C}'".

        Own Id: OTP-19421 Aux Id: GH-9173, PR-9276

      • A few minor issues were corrected in m:syntax_tools, as well in the erl_anno module.

        Own Id: OTP-19422 Aux Id: PR-9253

      • dets could print error messages to standard output when repairing DETS files. This has been changed to send the messages to logger.

        ets:fun2ms would print an error message to standard output as well as returning an error tuple. The printing of the message has been removed.

        Own Id: OTP-19427 Aux Id: PR-9232, PR-9446

      • The functions for converting to and from the RFC1339 date and time format would not properly handle fractional seconds for negative times.

        Own Id: OTP-19441 Aux Id: GH-9279, PR-9280

      • Replaced calls to deprecated crypto:start() with application:start(crypto).

        Own Id: OTP-19485 Aux Id: PR-8592

      • Fixed a bug when calling shell completion on a reserved word followed by a ( would crash the shell.

        Own Id: OTP-19511 Aux Id: GH-9470

      • Corrected the spec of ets:update_element/4.

        Own Id: OTP-19514 Aux Id: PR-9504

      • Corrected the spec for ets:info/1.

        Own Id: OTP-19515 Aux Id: PR-9514

      • Fixed crash when defining records with a string field in the shell

        Own Id: OTP-19533 Aux Id: GH-9557

      • Details in the hibernation implementation and time-out handling has been improved for gen_statem. In particular to avoid selective receive when cancelling a time-out.

        Own Id: OTP-19540 Aux Id: PR-9579

      • Fixed a bug when getting help on a module compiled without debug_info.

        Own Id: OTP-19583 Aux Id: PR-9654

      • Fix zip extraction to wrap invalid DOS timestamps to their correct value instead of returning the actual value. Before this fix the timestamp returned could have a second greater than 59. The bug has been present since Erlang/OTP 27.1.

        Own Id: OTP-19593 Aux Id: PR-9537, GH-9536

      • Enhance specs of timeout for improving documentation and dialyzer analysis.

        Own Id: OTP-19604 Aux Id: PR-9574

      Improvements and New Features

      • Singleton type variables in an union type do not make sense from Dialyzer's point of view. The following example is ill-typed:

        -spec run_test(Opts) -> term()
        +      when Opts :: {join_specs, Bool} | {test, Bool}.

        This used to be reported as a warning. In OTP-28, this is an error

        Own Id: OTP-19125 Aux Id: PR-8556

      • By default, sets created by the sets module will now be represented as maps.

        Own Id: OTP-19127 Aux Id: PR-8429

      • For various error types, the compiler now tries to suggest potential fixes by adding "did you mean ...?" at the end of error messages.

        When a function is used with wrong arity, the compiler will try to suggest a defined function with the same name but a different arity. For example, given the following module:

        -module(typos).
        +-export([t/0]).
        +bar(A) -> A.
        +bar(A,A,A) -> A.
        +bar(A,A,A,A) -> A.
        +t() -> bar(0, 0).

        The compiler will emit the following message:

        typo.erl:6:12: function bar/2 undefined, did you mean bar/1,3,4?
         %   6|     t() -> bar(0, 0).
        -%    |            ^

        For compiler errors that can easily be caused by typos, the compiler will try to suggest what the correct variable or function name, could be. For example, given the following module:

        -module(typos).
        --export([bar/2]).
        +%    |            ^

        For compiler errors that can easily be caused by typos, the compiler will try to suggest what the correct variable or function name, could be. For example, given the following module:

        -module(typos).
        +-export([bar/2]).
         
        -bar(A0, B0) ->
        +bar(A0, B0) ->
             A + B.

        the compiler will emit the following error messages:

        typos.erl:5:5: variable 'A' is unbound, did you mean 'A0'?
         %    5|     A + B.
         %     |     ^
         
         typos.erl:5:9: variable 'B' is unbound, did you mean 'B0'?
         %    5|     A + B.
        -%     |         ^

        Error types that now suggest correct arities: bad_inline, undefined_nif, bad_nowarn_unused_function, bad_nowarn_bif_clash, undefined_function.

        Error types that now suggest correct names: bad_inline, undefined_nif, bad_nowarn_unused_function, undefined_on_load, undefined_function, undefined_record, undefined_field, unbound_var.

        Using a function with wrong arity has higher precedence than having a typo in the function name. If the compiler can find a defined function with the same name but a different arity, it will not suggest a defined function with a close-enough name, regardless of arity.

        Own Id: OTP-19180 Aux Id: PR-8699, PR-9094

      • Comprehensions have been extended with zip generators according to EEP 73.

        Example:

        1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
        -[5,7,9]

        Own Id: OTP-19184 Aux Id: PR-8926

      • Before restarting a child, a supervisor must check if the restart limit is reached. This adds a penalty to the overall restart time, which should be kept low. The algorithm +% | ^

      Error types that now suggest correct arities: bad_inline, undefined_nif, bad_nowarn_unused_function, bad_nowarn_bif_clash, undefined_function.

      Error types that now suggest correct names: bad_inline, undefined_nif, bad_nowarn_unused_function, undefined_on_load, undefined_function, undefined_record, undefined_field, unbound_var.

      Using a function with wrong arity has higher precedence than having a typo in the function name. If the compiler can find a defined function with the same name but a different arity, it will not suggest a defined function with a close-enough name, regardless of arity.

      Own Id: OTP-19180 Aux Id: PR-8699, PR-9094

    • Comprehensions have been extended with zip generators according to EEP 73.

      Example:

      1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
      +[5,7,9]

      Own Id: OTP-19184 Aux Id: PR-8926

    • Before restarting a child, a supervisor must check if the restart limit is reached. This adds a penalty to the overall restart time, which should be kept low. The algorithm has been optimized from 2*O(n) to O(n) behavior.

      Own Id: OTP-19204 Aux Id: PR-8261

    • Added the possibility to configure shell docs column width through the stdlib parameter shell_docs_columns.

      Own Id: OTP-19224 Aux Id: PR-8651

    • The io:setopts/2 function now accepts the line_history option for more explicit handling of when to save shell history.

      Own Id: OTP-19230 Aux Id: PR-8792

    • The shell now prints a help message explaining how to interrupt a running command when stuck executing a command for longer than 5 seconds.

      Own Id: OTP-19231 Aux Id: PR-8793

    • Binaries can now be used as input to calendar:rfc3339_to_system_time/2, and produced as output of calendar:system_time_to_rfc3339/2.

      Own Id: OTP-19250 Aux Id: PR-8812

    • The erl -noshell mode has been updated to have two sub modes called raw and cooked, where cooked is the old default behaviour and raw can be used to bypass the line-editing support of the native terminal. Using raw mode it is possible to read keystrokes as they happen without the user having to press Enter. Also, the raw mode does not echo the typed characters to stdout. An example of how to create a tic-tac-toe game using this mechanism is included in the documentation.

      Own Id: OTP-19314 Aux Id: PR-8962, GH-8037

    • Added io:get_password/0 that can read passwords from stdin when in "raw" -noshell mode.

      Own Id: OTP-19315 Aux Id: PR-8962, PR-9006

    • New strict generators have been added for comprehensions.

      The currently existing generators are "relaxed": they ignore terms in the right-hand side expression that do not match the left-hand side pattern.

      The new strict generators fail with exception badmatch if a pattern doesn't match.

      Examples:

      Using the current relaxed generator operator <-, any element not matching -the pattern {_,_} will be silently discarded:

      1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
      -[{ok,1},{error,2}]

      If the intention is that all lists processed by a list comprehension must only +the pattern {_,_} will be silently discarded:

      1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
      +[{ok,1},{error,2}]

      If the intention is that all lists processed by a list comprehension must only contain tuples of size two, using the new strict version of the operator ensures -that term not matching will cause a crash:

      2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
      +that term not matching will cause a crash:

      2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
       ** exception error: no match of right hand side value ok

      Using the strict generator operator to mark the intention that all list elements must match the pattern could help finding mistakes quicker if something unpexected is added to the list processed by the generator.

      The strict version for bitstring generators is <:=.

      Own Id: OTP-19317 Aux Id: PR-8625

    • New options for suppressing behaviour warnings have been added:

      • nowarn_conflicting_behaviours
      • nowarn_undefined_behaviour_func
      • nowarn_undefined_behaviour
      • nowarn_undefined_behaviour_callbacks
      • nowarn_ill_defined_behaviour_callbacks
      • nowarn_ill_defined_optional_callbacks

      Own Id: OTP-19334 Aux Id: GH-8985, PR-9020

    • The join(Binaries, Separator) function that joins a list of binaries has been added to the binary module.

      Own Id: OTP-19337 Aux Id: GH-8099, PR-8100

    • The supervisor:which_child/2 function has been added to facilitate getting the pid of a sibling process; that is a process under same supervisor as the process that calls to call the new function.

      Own Id: OTP-19345 Aux Id: PR-8976

    • The function erl_anno:set_end_location/2 for setting the end location of a token has been added.

      Own Id: OTP-19354 Aux Id: PR-8966

    • Added a warning for calling non-exported functions with the remote function call syntax from the same module, and likewise for the remote fun syntax.

      Own Id: OTP-19371 Aux Id: GH-9092, PR-9095

    • The warn_deprecated_catch option enables warnings for use of old-style catch expressions on the form catch Expr instead of the modern try ... catch ... end. To prevent new uses of uses of old catches to be added, this compiler option can be enabled on the project level and -compile(nowarn_deprecated_catch). added to individual files that still contain old catches.

      Own Id: OTP-19425 Aux Id: PR-9154

    • Module re has been updated to use PCRE2, which is mostly backward compatible with PCRE.

      The most noticeable incompatibilities are

      • The default character encoding is pure ASCII and not Latin1. Unicode support is still available with options unicode and ucp.
      • Options bsr_anycrlf, bsr_unicode and {newline,_} are only set when a -regex is compiled and cannot be changed at matching for precompiled regex.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19431 Aux Id: PR-9299, PR-9610

    • Defining a fun in terms of an imported function is not allowed. Before this release, the compiler would not catch this kind of error if the name of the imported function happened to be a BIF. Consider this example:

      -module(fun_example).
      --export([foo/0, bar/0]).
      --import(m, [max/2, not_a_bif/0]).
      +regex is compiled and cannot be changed at matching for precompiled regex.

    POTENTIAL INCOMPATIBILITY

    Own Id: OTP-19431 Aux Id: PR-9299, PR-9610

  • Defining a fun in terms of an imported function is not allowed. Before this release, the compiler would not catch this kind of error if the name of the imported function happened to be a BIF. Consider this example:

    -module(fun_example).
    +-export([foo/0, bar/0]).
    +-import(m, [max/2, not_a_bif/0]).
     
    -foo() ->
    +foo() ->
         fun max/2.
     
    -bar() ->
    +bar() ->
         fun not_a_bif/0.

    The compiler in Erlang/OTP 27 would generate the following messages:

    fun_example.erl:9:5: function not_a_bif/0 undefined
     %    9|     fun not_a_bif/0.
     %     |     ^
    @@ -78,37 +78,37 @@
     fun_example.erl:3:2: Warning: import directive overrides auto-imported BIF max/2 --
     use "-compile({no_auto_import,[max/2]})." to resolve name clash
     %    3| -import(m, [max/2, not_a_bif/0]).
    -%     |  ^

    Also, attempting to call a local function having the same name as auto-imported BIF would result in an error if the BIF was added to Erlang/OTP before R14, and a warning for newer BIFs. This has been changed to always emit a warning. For example:

    -module(bif_example).
    --export([bar/1]).
    +%     |  ^

    Also, attempting to call a local function having the same name as auto-imported BIF would result in an error if the BIF was added to Erlang/OTP before R14, and a warning for newer BIFs. This has been changed to always emit a warning. For example:

    -module(bif_example).
    +-export([bar/1]).
     
    -bar(B) ->
    -    is_boolean(B).
    +bar(B) ->
    +    is_boolean(B).
     
    -is_boolean(B) ->
    +is_boolean(B) ->
             B =:= true orelse B =:= false.

    will now result in the following warning instead of an error:

    if_example.erl:5:5: Warning: ambiguous call of overridden auto-imported BIF is_boolean/1 --
     use erlang:is_boolean/1 or "-compile({no_auto_import,[is_boolean/1]})." to resolve name clash
     %    5|     is_boolean(B).
     %     |     ^

    Own Id: OTP-19432 Aux Id: PR-9246

  • It is now possible to use any base for floating point numbers as described in EEP 75: Based Floating Point Literals.

    Computers represent floating point numbers in binary, but such numbers are typically printed using base ten, for example 0.314159265e1. To maintain exact bit-level precision when converting numbers to and from text, it is better to use a base that matches the internally used base, such as 16 for a compact but still exact representation, or 2 for visualizing or writing down the exact internal format. One particular case where such exact representations are useful is in code generating tools.

    Examples:

    > 2#0.111.
     0.875
     > 16#fefe.fefe#e16.
    -1.2041849337671418e24

    Own Id: OTP-19452 Aux Id: PR-9106

  • The callback function handle_continue/2 in gen_server callback modules is now cached like the others, thanks to code cleanup and optimization of the internal behaviour loop.

    This should only improve performance, not affect functionality.

    Own Id: OTP-19474 Aux Id: PR-9333

  • Encoding done by the json module has been optimized.

    Own Id: OTP-19476 Aux Id: PR-9251

  • There is a new zstd module that does Zstandard compression.

    Own Id: OTP-19477 Aux Id: PR-9316

  • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

    Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

  • Functions of a module can now be grouped in the shell code completion by using the group key in the -doc attribute e.g. -doc(#{group=><<"Public API">>). fetch()->....

    Functions, callbacks and types in the module reference documentation of OTP is now grouped using this feature.

    Own Id: OTP-19483 Aux Id: PR-9408

  • Added calendar:universal_time_to_system_time/1,2 and calendar:local_time_to_system_time/1,2

    Own Id: OTP-19505 Aux Id: PR-9445

  • Improve error messages for json:decode/1.

    Own Id: OTP-19508 Aux Id: PR-9484

  • ETS heir can be set without getting an ETS-TRANSFER message. Useful when the heir is a supervisor process that cannot handle custom messages.

    Own Id: OTP-19512 Aux Id: PR-7970

  • Added support for the Unicode 16 standard.

    Own Id: OTP-19516 Aux Id: PR-9518, PR-9141

  • When documenting a function or type that needs to deal with durations, usually we can document it as "time in milliseconds". Since the timer family of functions (hms, hours, seconds, ...) all return time in milliseconds, it is useful to be able to use this type in type specifications.

    Own Id: OTP-19526 Aux Id: PR-9515

  • A new event time-out has been implemented in gen_server, that behaves more like the one in gen_statem.

    See the type gen_server:action/0 for {timeout|hibernate,...}, and also related functions.

    Own Id: OTP-19537 Aux Id: PR-9287, PR-9615, PR-9621

  • Line numbers used to be reported in the following way:

    1> lists:last([]).
    -** exception error: no function clause matching lists:last([]) (lists.erl, line 389)

    Starting from Erlang/OTP 28, line numbers are now reported in the following way:

    1> lists:last([]).
    +1.2041849337671418e24

    Own Id: OTP-19452 Aux Id: PR-9106

  • The callback function handle_continue/2 in gen_server callback modules is now cached like the others, thanks to code cleanup and optimization of the internal behaviour loop.

    This should only improve performance, not affect functionality.

    Own Id: OTP-19474 Aux Id: PR-9333

  • Encoding done by the json module has been optimized.

    Own Id: OTP-19476 Aux Id: PR-9251

  • There is a new zstd module that does Zstandard compression.

    Own Id: OTP-19477 Aux Id: PR-9316

  • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

    Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

  • Functions of a module can now be grouped in the shell code completion by using the group key in the -doc attribute e.g. -doc(#{group=><<"Public API">>). fetch()->....

    Functions, callbacks and types in the module reference documentation of OTP is now grouped using this feature.

    Own Id: OTP-19483 Aux Id: PR-9408

  • Added calendar:universal_time_to_system_time/1,2 and calendar:local_time_to_system_time/1,2

    Own Id: OTP-19505 Aux Id: PR-9445

  • Improve error messages for json:decode/1.

    Own Id: OTP-19508 Aux Id: PR-9484

  • ETS heir can be set without getting an ETS-TRANSFER message. Useful when the heir is a supervisor process that cannot handle custom messages.

    Own Id: OTP-19512 Aux Id: PR-7970

  • Added support for the Unicode 16 standard.

    Own Id: OTP-19516 Aux Id: PR-9518, PR-9141

  • When documenting a function or type that needs to deal with durations, usually we can document it as "time in milliseconds". Since the timer family of functions (hms, hours, seconds, ...) all return time in milliseconds, it is useful to be able to use this type in type specifications.

    Own Id: OTP-19526 Aux Id: PR-9515

  • A new event time-out has been implemented in gen_server, that behaves more like the one in gen_statem.

    See the type gen_server:action/0 for {timeout|hibernate,...}, and also related functions.

    Own Id: OTP-19537 Aux Id: PR-9287, PR-9615, PR-9621

  • Line numbers used to be reported in the following way:

    1> lists:last([]).
    +** exception error: no function clause matching lists:last([]) (lists.erl, line 389)

    Starting from Erlang/OTP 28, line numbers are now reported in the following way:

    1> lists:last([]).
     ** exception error: no function clause matching lists:last([]) (lists.erl:389)

    Own Id: OTP-19538 Aux Id: PR-9468

  • Upgrade pcre2 to 10.45

    Own Id: OTP-19541 Aux Id: PR-9582

  • Added functions that produce utf-8 binaries instead of iolists. New functions are: io_lib:bformat/2, io_lib:bformat/3, io_lib:bfwrite/2, io_lib:bfwrite/3, io_lib:bwrite/2 and io_lib:bwrite_string/3.

    Own Id: OTP-19556 Aux Id: PR-9772

  • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

    Own Id: OTP-19575 Aux Id: PR-9670

  • A list of PCRE2 incompatibilities is documented in a user's guide for stdlib.

    Own Id: OTP-19578 Aux Id: PR-9705

  • Change automatic hibernation of static supervisors so that they will hibernate after being idle for 1 second instead of only after starting, dynamic supervisors (simple_one_for_one) will not be hibernated at all. An option to the supervisor is added to make it configurable for the application. This option defaults to 1 second for static supervisors and to infinity for the simple_one_for_one supervisors.

    POTENTIAL INCOMPATIBILITY

    Own Id: OTP-19597 Aux Id: PR-9680

  • STDLIB 6.2.2.3

    Fixed Bugs and Malfunctions

    • Fixed bug in ets:update_counter/4 and ets:update_element/4 accepting and inserting a default tuple smaller than the keypos of the table. Such a tuple without a key element would make the table internally inconsistent and might lead to bad behavior at table access, like ERTS runtime crash.

      Now a call to ets:update_counter/4 or ets:update_element/4 will fail with badarg if the key does not exist in the table and the default tuple is too small.

      Own Id: OTP-19962 Aux Id: PR-10616

    • For a function that started with a bracket-only pattern (such as []), the ?FUNCTION_ARITY macro would evaluate to one less than the actual arity.

      Own Id: OTP-19988 Aux Id: GH-10705, PR-10708

    STDLIB 6.2.2.2

    Fixed Bugs and Malfunctions

    • A set of small bugs in sort stability for `lists:sort/1` and `lists:keysort/1` has been fixed. The bug happened for only some, seemingly random, element sequences. Most sorts were stable.

      Sort stability for `lists:sort/1` is only possible to observe when sorting lists with floating point and integer numbers of the same value.

      For `lists:keysort/1` the list had to start with two tuples where the keys or the whole tuples compared equal.

      Own Id: OTP-19673 Aux Id: ERIERL-1240

    STDLIB 6.2.2.1

    Fixed Bugs and Malfunctions

    • The save_module/1 command in the shell now saves both the locally defined records and the imported records using the rr/1 command.

      Own Id: OTP-19647 Aux Id: GH-9816, PR-9897

    • It's now possible to write lists:map(fun is_atom/1, []) or lists:map(fun my_func/1, []), in the shell, instead of lists:map(fun erlang:is_atom/1, []) or lists:map(fun shell_default:my_func/1, []).

      Own Id: OTP-19649 Aux Id: GH-9771, PR-9898

    • Properly strip the leading / and drive letter from filepaths when zipping and unzipping archives.

      Thanks to Wander Nauta for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

      Own Id: OTP-19653 Aux Id: CVE-2025-4748, PR-9941

    • Shell no longer crashes when requesting to autocomplete map keys containing non-atoms.

      Own Id: OTP-19659 Aux Id: PR-9896

    • A remote shell can now exit by closing the input stream, without terminating the remote node.

      Own Id: OTP-19667 Aux Id: PR-9912

    STDLIB 6.2.2

    Fixed Bugs and Malfunctions

    • Fixed crash when fetching initial_call when user code have modified the process_dictionary.

      Own Id: OTP-19546 Aux Id: ERIERL-1205, PR-9596

    STDLIB 6.2.1

    Fixed Bugs and Malfunctions

    • Fixed argparse:help/2 to accept the program name as part of the command path.

      Own Id: OTP-19397 Aux Id: PR-9160

    • Fixed argparse:format_help/2 crash on 'hidden' command.

      Own Id: OTP-19400 Aux Id: PR-9151, GH-9150

    • Fixed the type specification for timer:sleep/1 by adding the value infinity to its input type.

      Own Id: OTP-19442 Aux Id: PR-9303

    • Eliminated a crash in zip:unzip/1 while unzipping an archive where a directory within was read-only. This bug was introduced in Erlang/OTP 27.1.

      Own Id: OTP-19447 Aux Id: GH-9332, PR-9335

    • Fixed map comprehension result when a key value is replaced.

      Own Id: OTP-19459 Aux Id: GH-9348, PR-9358

    • Fixed string:jaro_similarity/1 for matching strings of length 1.

      Own Id: OTP-19468 Aux Id: PR-9371

    STDLIB 6.2

    Fixed Bugs and Malfunctions

    • Made it possible to expand help text displayed by pressing ^[h by pressing ^[h again.

      Own Id: OTP-19260 Aux Id: PR-8884

    • Defining a fun in the shell using the syntax fun Name/Arity would fail. This has been corrected so that the following now works:

      1> F = fun is_atom/1.
       #Fun.erl.42.18682967>
      -> F(a).
      +> F(a).
       true
       3> Id = fun id/1.
       #Fun.erl.42.18682967>
      -4> Id(42).
      +4> Id(42).
       ** exception error: undefined shell command id/1
      -5> id(I) -> I.
      +5> id(I) -> I.
       ok
      -6> Id(42).
      -42

      The Debugger has also been corrected to correctly handle this syntax for a BIF.

      Own Id: OTP-19322 Aux Id: GH-8963, PR-8987

    • Fixed a bug where completion of 'fun(' would cause the shell to crash.

      Own Id: OTP-19351 Aux Id: PR-9043

    • Fixed a bug causing the shell to crash while trying to complete an expression starting with a '/' or a variable followed by '(' or '/'. E.g. Foo/ and Foo(.

      Own Id: OTP-19361 Aux Id: PR-9078

    • zip:extract/2 with keep_old_files now respects the cwd option.

      Own Id: OTP-19370 Aux Id: PR-9097, GH-9087

    • Fixed an error in uri_string:percent_decode spec

      Own Id: OTP-19380 Aux Id: GH-8755

    Improvements and New Features

    • Updated shell docs to display the type spec, that is, h(erlang, min, 2)) now prints the type spec and documentation in the shell.

      > h(erlang,min,2).
      +6> Id(42).
      +42

      The Debugger has also been corrected to correctly handle this syntax for a BIF.

      Own Id: OTP-19322 Aux Id: GH-8963, PR-8987

    • Fixed a bug where completion of 'fun(' would cause the shell to crash.

      Own Id: OTP-19351 Aux Id: PR-9043

    • Fixed a bug causing the shell to crash while trying to complete an expression starting with a '/' or a variable followed by '(' or '/'. E.g. Foo/ and Foo(.

      Own Id: OTP-19361 Aux Id: PR-9078

    • zip:extract/2 with keep_old_files now respects the cwd option.

      Own Id: OTP-19370 Aux Id: PR-9097, GH-9087

    • Fixed an error in uri_string:percent_decode spec

      Own Id: OTP-19380 Aux Id: GH-8755

    Improvements and New Features

    • Updated shell docs to display the type spec, that is, h(erlang, min, 2)) now prints the type spec and documentation in the shell.

      > h(erlang,min,2).
       
      -  -spec min(Term1, Term2) -> Minimum
      -               when Term1 :: term(), Term2 :: term(), Minimum :: term().
      +  -spec min(Term1, Term2) -> Minimum
      +               when Term1 :: term(), Term2 :: term(), Minimum :: term().
       
         Returns the smallest of Term1 and Term2. If the terms compare equal with the == operator, Term1 is returned.

      Own Id: OTP-19234 Aux Id: GH-8544, PR-8833

    • The file:io_device/0 type has been updated to clearly show the difference between a raw and cooked IoDevice.

      Own Id: OTP-19301 Aux Id: PR-8956

    • Added json:format_key_value_list/3 and json:format_key_value_list_checked/3.

      Own Id: OTP-19320 Aux Id: PR-8889

    • Improved documentation of timers.

      Own Id: OTP-19360 Aux Id: ERIERL-1149, PR-9062

    • Added logging support to io:user/0, io:standard_io/0 and io:standard_error/0. See io:setopts/2 for more details.

      Own Id: OTP-19372 Aux Id: PR-8947

    STDLIB 6.1.2

    Fixed Bugs and Malfunctions

    • With this change, uri_string:normalize assumes empty path (do not crash) when no path is provided in the URI map.

      Own Id: OTP-19266 Aux Id: ERIERL-1127, PR-8890

    • Fixed spec for json:format/3.

      Own Id: OTP-19286 Aux Id: GH-8880, PR-8914

    STDLIB 6.1.1

    Fixed Bugs and Malfunctions

    • Remove whitespace stripping of returned binaries in json:decode/3.

      Own Id: OTP-19227 Aux Id: ERIERL-1130, PR-8809

    • Fix zip:unzip/2 to not crash when extracting zip files with garbage in the Zip64 extra header. This bug was introduced in Erlang 27.1 and has so far only been seen on some archives creates by MS Excel.

      Own Id: OTP-19241 Aux Id: PR-8836

    • With this change, shutdown procedure handles a race condition between supervisor executing a shutdown and child process termination from other reason.

      Own Id: OTP-19256 Aux Id: PR-8780

    STDLIB 6.1

    Fixed Bugs and Malfunctions

    • The help printout for incorrect io:format/0 strings now handles the k modifier correctly.

      Own Id: OTP-19146 Aux Id: PR-8611, GH-8568

    • Fixed a bug that caused the shell completion to crash when keyword and tuple appeared on the same line.

      Own Id: OTP-19157 Aux Id: PR-8638

    • Due to PR-7419/OTP-18671, the cached internal value of the callback_mode started leaking out to logger reports, which could cause logger handlers to crash. This has now been fixed to show the value that was set, as before caching.

      Own Id: OTP-19164 Aux Id: GH-8605, PR-7419, OTP-18671

    • Fixed an emulator crash relating to compressed ETS tables.

      Own Id: OTP-19176 Aux Id: PR-8683

    • The error description for maps:update/3 will no longer insist that the third argument is not a map when a key could not be found

      Own Id: OTP-19189

    • Multiple issues have been corrected in the markdown parser that creates documentation for the shell.

      The parser was incorrectly parsing formatted markdown (either bold or italics) within parenthesis. This used to not be shown correctly in the shell documentation (_Option._), which was displayed verbatim. This fix makes Option. to appear in italics.

      The markdown parser is also used in the creation of other documentation formats, so this was a bug that affected other generated documentation formats.

      Own Id: OTP-19200 Aux Id: GH-8738, PR-8739

    • Fixed category for some codepoint ranges in unicode_util.

      Own Id: OTP-19210 Aux Id: GH-8748

    • Fixed argparse to print sub-commands help when available.

      Own Id: OTP-19222 Aux Id: PR-8777

    Improvements and New Features

    • Class annotation to HTML from fenced blocks have been added.

      Own Id: OTP-19105 Aux Id: PR-8499

    • Added JSON formatting functions for indented output.

      Own Id: OTP-19112

    • Improved illegal pattern error for accidental map associations.

      Own Id: OTP-19128 Aux Id: PR-8555

    • Progress reports for a dynamically started supervisor will now be logged at debug level.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19202 Aux Id: PR-8261, GH-8715, PR-8741

    • The zip module has been updated with support for:

      • zip64 archives - Archives larger than 4GB or with more than 2^32 entries.
      • extended timestamps - Higher resolution and in UTC.
      • UID/GID - Save and extract the original UID/GID.
      • Fixes so that permission mode attributes are correctly read and set for files in archives.
      • zip:list_dir/2 now also returns directories, not only files. (You can disable this behaviour by using the option skip_directories).

      Various bugs in the original implementation have also been fixed, such as:

      • Correctly encode and decode the DOS timestamps for entries within an archive (that is the non-extended timestamp).
      • Fix DOS timestamps to be set to localtime instead of UTC (use extended timestamps for UTC timestamps).
      • Use the unix file attributes read from disk when creating archives instead of setting everything to 644.

      Own Id: OTP-19214 Aux Id: PR-8765

    STDLIB 6.0.1

    Fixed Bugs and Malfunctions

    STDLIB 6.0

    Fixed Bugs and Malfunctions

    • The specs in module binary has been updated to reflect what is allowed by the documentation.

      Own Id: OTP-18684 Aux Id: PR-7481

    • Several functions in the binary module would accept arguments of the wrong type under certain circumstances. In this release, they now raise an exception when incorrect types are given.

      The following functions would accept an invalid pattern if the subject binary was empty or if the {scope,{0,0}} option was given: @@ -116,8 +116,8 @@ binary:matches/2,3, binary:replace/3,4, and binary:split/2,3

      The call binary:copy(<<1:1>>, 0) would return an empty binary instead of raising an exception. Similarly, calls to binary:part/2,3 attempting to extract 0 bytes at position 0 of a bitstring would return an empty binary instead of raising an exception.

      Own Id: OTP-18743 Aux Id: PR-7607, PR-7628

    • The documentation for the preprocessor now mentions that defined(Name) can be called in the condition for an -if or -elif directive to test whether Name is the name of a defined macro. (This feature was implemented in OTP 21.)

      If a function call in an -if or -elif with a name that is not the name of a guard BIF, there would not be a compilation error, but would instead cause the lines following the directive to be skipped. This has now been changed to be a compilation error.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-18784 Aux Id: GH-7706, PR-7726

    • get_until requests using the I/O protocol now correctly return a binary or list when eof is the last item returned by the callback.

      Own Id: OTP-18930 Aux Id: PR-7993, GH-4992

    • The error handling the simple_one_for_one supervisor has been enhanced. A transient child returning ignore will no longer cause a crash.

      Also, automatic shutdown has been disabled because it does not make sense for this supervisor type. That is was allowed is considered a bug. Therefore, we don't consider this an incompatible change.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19029 Aux Id: PR-8230

    • Fix shell expansion to not crash when expanding a map with non-atom keys and to not list zero arity functions when an argument has been given.

      Own Id: OTP-19073 Aux Id: PR-8375, GH-8366, GH-8365, GH-8364

    Improvements and New Features

    • The functions is_equal/2, map/2, and filtermap/2 have been added to the modules sets, ordsets, and gb_sets.

      Own Id: OTP-18622 Aux Id: PR-7183, PR-7232

    • The compiler now emits nicer error message for function head mismatches. -For example, given:

      a() -> ok;
      -a(_) -> error.

      Erlang/OTP 26 and earlier would emit a diagnostic similar to:

      t.erl:6:1: head mismatch
      +For example, given:

      a() -> ok;
      +a(_) -> error.

      Erlang/OTP 26 and earlier would emit a diagnostic similar to:

      t.erl:6:1: head mismatch
       %    6| a(_) -> error.
       %     | ^

      while in Erlang/OTP 27 the diagnostic is similar to:

      t.erl:6:1: head mismatch: function a with arities 0 and 1 is regarded as two distinct functions. Is the number of arguments incorrect or is the semicolon in a/0 unwanted?
       %    6| a(_) -> error.
      @@ -140,22 +140,22 @@
       my_label              c:pinfo/2                               51
       4> proc_lib:get_label(self()).
       my_label

      Own Id: OTP-18789 Aux Id: PR-7720, PR-8003

    • -callback attributes has been added to modules sys and erl_error.

      Own Id: OTP-18793 Aux Id: PR-7703

    • Several new functions that accept funs have been added to module timer.

      Functions apply_after/2, apply_interval/2, and apply_repeatedly/2 accept a nullary fun as the second argument, while functions apply_after/3, apply_interval/3, and apply_repeatedly/3 accept an n-ary fun as the second and a list of n arguments for the fun as the third argument.

      Own Id: OTP-18808 Aux Id: PR-7649

    • Sigils on string literals have been implemented as per EEP 66, that is: binary and string sigils in verbatim and escape characters variants, as well as a default (vanilla) Sigil. All for ordinary strings and for triple-quoted strings (EEP 64). See Sigils in the Reference Manual.

      Examples:

      1> ~"Björn".
      -<<"Björn"/utf8>>
      +<<"Björn"/utf8>>
       2> ~b"Björn".
      -<<"Björn"/utf8>>
      +<<"Björn"/utf8>>
       3> ~S"\s*(\w+)".
       "\\s*(\\w+)"
       4> ~B"\s*(\w+)".
      -<<"\\s*(\\w+)">>

      Own Id: OTP-18825 Aux Id: OTP-18750, PR-7684

    • Functions shell:default_multiline_prompt/1, shell:inverted_space_prompt/1, and +<<"\\s*(\\w+)">>

    Own Id: OTP-18825 Aux Id: OTP-18750, PR-7684

  • Functions shell:default_multiline_prompt/1, shell:inverted_space_prompt/1, and shell:prompt_width/1 have been exported to help with custom prompt implementations.

    Own Id: OTP-18834 Aux Id: PR-7675, PR-7816

  • The shell now pages long output from the documentation help command (h(Module)), auto completions and the search command.

    Own Id: OTP-18846 Aux Id: PR-7845

  • The M-h hotkey (Alt/Option-h) now outputs help for the module or function directly before the cursor.

    Own Id: OTP-18847 Aux Id: PR-7846

  • Added support for adding a custom code formatter that formats your multi-line shell commands in your preferred formatting on submission. See shell:format_shell_func/ and shell:erl_pp_format_func/1.

    Own Id: OTP-18848 Aux Id: PR-7847

  • Added shell functions for viewing, forgetting and saving locally defined functions, types and records.

    Own Id: OTP-18852 Aux Id: PR-7844

  • Added string:jaro_similarity/2, which can be used to calculate the similarity between two strings.

    Own Id: OTP-18865 Aux Id: PR-7879

  • The new function ets:update_element/4 is similar to ets:update_element/3, but takes a default tuple as the fourth argument, which will be inserted if no previous record with that key exists.

    Own Id: OTP-18870 Aux Id: PR-7857

  • Added functions to retrieve the next higher or lower key/element from gb_trees and gb_sets, as well as returning iterators that start at given keys/elements.

    Own Id: OTP-18874 Aux Id: PR-7745

  • When the shell built-in function c/1,2 is used to re-compile a module, the current working directory of the original compilation is now added to the include path.

    Own Id: OTP-18908 Aux Id: PR-7957

  • The timer module now uses a private table for its internal state, slightly improving its performance.

    Own Id: OTP-18914 Aux Id: PR-7973

  • EEP-59 - Documentation Attributes has been implemented.

    Documentation attributes can be used to document functions, types, callbacks, and modules. The keyword -moduledoc "Documentation here". is used to document modules, while -doc "Documentation here". can be used on top of functions, types, and callbacks to document them, respectively.

    • Types, callbacks, and function documentation can be set to hidden either via -doc false or -doc hidden. When documentation attributes mark a type as hidden, they will not be part of the documentation.

    • The documentation from moduledoc and doc gets added by default to the binary beam file, following the format of EEP-48.

    • Using the compiler flag warn_missing_doc will raise a warning when -doc attributes are missing in exported functions, types, and callbacks.

    • Using the compiler flag warn_missing_spec_documented will raise a warning when -spec attributes are missing in documented functions, types, and callbacks.

    • moduledocs and docs may refer to external files to be embedded, such as -doc {file, "README.md"}., which refers to the file README.md found in the current working directory.

    • The compiler warns about exported functions whose specs refer to hidden types. Thus, there will be warnings when a hidden type (meaning, the type is not part of the documentation) gets used in an exported function.

    Own Id: OTP-18916 Aux Id: PR-7936

  • New ets functions ets:first_lookup/1, ets:next_lookup/2, ets:prev_lookup/2 and ets:last_lookup/1. Example: ets:next_lookup/1 is equivalent to ets:next/2 followed by ets:lookup/2 with the next key. The new combined functions are more efficient and with guaranteed atomicity.

    Own Id: OTP-18923 Aux Id: PR-6791

  • The maybe expression is now enabled by default.

    To use maybe as an atom, it needs to be single-quoted. Alternatively, the maybe expression can be disabled by disabling the maybe_expr feature. That can be done by placing the following the line at the beginning of an Erlang source file:

    -feature(maybe_expr, disable).

    Another way to disable the maybe_expr feature is by passing the -disable-feature option to erlc:

    erlc -disable-feature maybe_expr some_file.erl

    Own Id: OTP-18944 Aux Id: PR-8067

  • The compiler will now raise a warning when updating record/map literals. As an example, consider this module:

    -module(t).
    --export([f/0]).
    --record(r, {a,b,c}).
    +spec attributes are missing in documented functions, types, and callbacks.

  • moduledocs and docs may refer to external files to be embedded, such as -doc {file, "README.md"}., which refers to the file README.md found in the current working directory.

  • The compiler warns about exported functions whose specs refer to hidden types. Thus, there will be warnings when a hidden type (meaning, the type is not part of the documentation) gets used in an exported function.

  • Own Id: OTP-18916 Aux Id: PR-7936

  • New ets functions ets:first_lookup/1, ets:next_lookup/2, ets:prev_lookup/2 and ets:last_lookup/1. Example: ets:next_lookup/1 is equivalent to ets:next/2 followed by ets:lookup/2 with the next key. The new combined functions are more efficient and with guaranteed atomicity.

    Own Id: OTP-18923 Aux Id: PR-6791

  • The maybe expression is now enabled by default.

    To use maybe as an atom, it needs to be single-quoted. Alternatively, the maybe expression can be disabled by disabling the maybe_expr feature. That can be done by placing the following the line at the beginning of an Erlang source file:

    -feature(maybe_expr, disable).

    Another way to disable the maybe_expr feature is by passing the -disable-feature option to erlc:

    erlc -disable-feature maybe_expr some_file.erl

    Own Id: OTP-18944 Aux Id: PR-8067

  • The compiler will now raise a warning when updating record/map literals. As an example, consider this module:

    -module(t).
    +-export([f/0]).
    +-record(r, {a,b,c}).
     
    -f() ->
    -    #r{a=1}#r{b=2}.

    The compiler raises the following warning:

    1> c(t).
    +f() ->
    +    #r{a=1}#r{b=2}.

    The compiler raises the following warning:

    1> c(t).
     t.erl:6:12: Warning: expression updates a literal
     %    6|     #r{a=1}#r{b=2}.
     %     |            ^

    Own Id: OTP-18951 Aux Id: PR-8069

  • The documentation has been migrated to use Markdown and ExDoc.

    Own Id: OTP-18955 Aux Id: PR-8026

  • Optimized ets:foldl and ets:foldr to use new ets:next_lookup. Also made them immune against table renaming.

    Own Id: OTP-18993 Aux Id: PR-8048

  • Windows now supports all functions in math.

    Own Id: OTP-19001 Aux Id: PR-8164

  • erl_lint (and by extension the compiler) will now warn for code using deprecated callbacks.

    The only callback currenly deprecated is format_status/2 in gen_server, gen_event and gen_statem.

    You can use nowarn_deprecated_callback to silence the warning.

    Own Id: OTP-19010 Aux Id: PR-8205

  • There is a new module json for encoding and decoding JSON.

    Both encoding and decoding can be customized. Decoding can be done in a SAX-like fashion and handle multiple documents and streams of data.

    Own Id: OTP-19020 Aux Id: PR-8111

  • STDLIB 5.2.3.6

    Fixed Bugs and Malfunctions

    • Fixed bug in ets:update_counter/4 and ets:update_element/4 accepting and inserting a default tuple smaller than the keypos of the table. Such a tuple without a key element would make the table internally inconsistent and might lead to bad behavior at table access, like ERTS runtime crash.

      Now a call to ets:update_counter/4 or ets:update_element/4 will fail with badarg if the key does not exist in the table and the default tuple is too small.

      Own Id: OTP-19962 Aux Id: PR-10616

    • For a function that started with a bracket-only pattern (such as []), the ?FUNCTION_ARITY macro would evaluate to one less than the actual arity.

      Own Id: OTP-19988 Aux Id: GH-10705, PR-10708

    STDLIB 5.2.3.5

    Fixed Bugs and Malfunctions

    • A set of small bugs in sort stability for `lists:sort/1` and `lists:keysort/1` has been fixed. The bug happened for only some, seemingly random, element sequences. Most sorts were stable.

      Sort stability for `lists:sort/1` is only possible to observe when sorting lists with floating point and integer numbers of the same value.

      For `lists:keysort/1` the list had to start with two tuples where the keys or the whole tuples compared equal.

      Own Id: OTP-19673 Aux Id: ERIERL-1240

    STDLIB 5.2.3.4

    Fixed Bugs and Malfunctions

    • It's now possible to write lists:map(fun is_atom/1, []) or lists:map(fun my_func/1, []), in the shell, instead of lists:map(fun erlang:is_atom/1, []) or lists:map(fun shell_default:my_func/1, []).

      Own Id: OTP-19649 Aux Id: GH-9771 PR-9898

    • Properly strip the leading / and drive letter from filepaths when zipping and unzipping archives.

      Thanks to Wander Nauta for finding and responsibly disclosing this vulnerability to the Erlang/OTP project.

      Own Id: OTP-19653 Aux Id: CVE-2025-4748 PR-9941

    • A remote shell can now exit by closing the input stream, without terminating the remote node.

      Own Id: OTP-19667 Aux Id: PR-9912

    STDLIB 5.2.3.3

    Fixed Bugs and Malfunctions

    • Fixed an error in uri_string:percent_decode spec

      Own Id: OTP-19380 Aux Id: GH-8755

    STDLIB 5.2.3.2

    Fixed Bugs and Malfunctions

    • With this change, shutdown procedure handles a race condition between supervisor executing a shutdown and child process termination from other reason.

      Own Id: OTP-19256 Aux Id: PR-8780

    • With this change, uri_string:normalize assumes empty path (do not crash) when no path is provided in the URI map.

      Own Id: OTP-19266 Aux Id: ERIERL-1127, PR-8890

    STDLIB 5.2.3.1

    Fixed Bugs and Malfunctions

    • Fixed a bug that caused the shell completion to crash when keyword and tuple appeared on the same line.

      Own Id: OTP-19157 Aux Id: PR-8638

    STDLIB 5.2.3

    Fixed Bugs and Malfunctions

    • Fix shell expansion of -type a() :: $a. in the erlang shell.

      Own Id: OTP-19062

    • Fix the shell Job Control Mode to not crash when typing TAB or CTRL+R.

      Own Id: OTP-19072 Aux Id: PR-8391

    STDLIB 5.2.2

    Fixed Bugs and Malfunctions

    • Attempting to use the maybe construct in a macro argument could crash the compiler.

      Own Id: OTP-19031 Aux Id: GH-8268

    STDLIB 5.2.1

    Fixed Bugs and Malfunctions

    • The help texts shown by argparse will now display sub-command arguments in the correct order.

      Own Id: OTP-18900 Aux Id: PR-7945, GH-7934

    • Clarified the argparse documentation regarding the user-defined help template.

      Own Id: OTP-18937

    • Fix shell expansion to not crash when expanding invalid using invalid atoms.

      Own Id: OTP-18953 Aux Id: GH-8016 PR-8075

    STDLIB 5.2

    Fixed Bugs and Malfunctions

    • Make shell_docs correctly trim the newline at the end of code blocks.

      Own Id: OTP-18777 Aux Id: PR-7663

    • Replaced unintentional Erlang Public License 1.1 headers in some files with /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/orddict.xhtml differs (HTML document, ASCII text, with very long lines (1551)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/orddict.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/orddict.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -30,13 +30,13 @@ as different if they do not match (=:=), this module considers two keys as different if and only if they do not compare equal (==).

      Notes

      Functions append/3 and append_list/3 are included so that keyed values can be stored in a list accumulator, for -example:

      > D0 = orddict:new(),
      -  D1 = orddict:store(files, [], D0),
      -  D2 = orddict:append(files, f1, D1),
      -  D3 = orddict:append(files, f2, D2),
      -  D4 = orddict:append(files, f3, D3),
      -  orddict:fetch(files, D4).
      -[f1,f2,f3]

      This saves the trouble of first fetching a keyed value, appending a new value to +example:

      > D0 = orddict:new(),
      +  D1 = orddict:store(files, [], D0),
      +  D2 = orddict:append(files, f1, D1),
      +  D3 = orddict:append(files, f2, D2),
      +  D4 = orddict:append(files, f3, D3),
      +  orddict:fetch(files, D4).
      +[f1,f2,f3]

      This saves the trouble of first fetching a keyed value, appending a new value to the list of stored values, and storing the result.

      Function fetch/2 is to be used if the key is known to be in the dictionary, otherwise function find/2.

      See Also

      dict, gb_trees

      @@ -403,16 +403,16 @@

      Appends a new Value to the current list of values associated with Key. An exception is generated if the initial value associated with Key is not a list -of values.

      See also section Notes.

      Example 1:

      1> OrdDict1 = orddict:from_list([{x, []}]).
      -[{x,[]}]
      -2> OrdDict2 = orddict:append(x, 1, OrdDict1).
      -[{x,[1]}]
      -3> OrdDict3 = orddict:append(x, 2, OrdDict2).
      -[{x,[1,2]}]
      -4> orddict:append(y, 3, OrdDict3).
      -[{x,[1,2]},{y,[3]}]

      Example 2:

      1> OrdDict1 = orddict:from_list([{a, no_list}]).
      -[{a,no_list}]
      -2> orddict:append(a, 1, OrdDict1).
      +of values.

      See also section Notes.

      Example 1:

      1> OrdDict1 = orddict:from_list([{x, []}]).
      +[{x,[]}]
      +2> OrdDict2 = orddict:append(x, 1, OrdDict1).
      +[{x,[1]}]
      +3> OrdDict3 = orddict:append(x, 2, OrdDict2).
      +[{x,[1,2]}]
      +4> orddict:append(y, 3, OrdDict3).
      +[{x,[1,2]},{y,[3]}]

      Example 2:

      1> OrdDict1 = orddict:from_list([{a, no_list}]).
      +[{a,no_list}]
      +2> orddict:append(a, 1, OrdDict1).
       ** exception error: bad argument
            in operator  ++/2
               called as no_list ++ [1]
      @@ -449,12 +449,12 @@

      Appends a list of values ValList to the current list of values associated with Key. An exception is generated if the initial value associated with Key is -not a list of values.

      See also section Notes.

      Example:

      1> OrdDict1 = orddict:from_list([{x, []}]).
      -[{x,[]}]
      -2> OrdDict2 = orddict:append_list(x, [1,2], OrdDict1).
      -[{x,[1,2]}]
      -3> OrdDict3 = orddict:append_list(y, [3,4], OrdDict2).
      -[{x,[1,2]},{y,[3,4]}]
      +not a list of values.

      See also section Notes.

      Example:

      1> OrdDict1 = orddict:from_list([{x, []}]).
      +[{x,[]}]
      +2> OrdDict2 = orddict:append_list(x, [1,2], OrdDict1).
      +[{x,[1,2]}]
      +3> OrdDict3 = orddict:append_list(y, [3,4], OrdDict2).
      +[{x,[1,2]},{y,[3,4]}]
      @@ -483,10 +483,10 @@ -

      Erases all items with a specified key from a dictionary.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:erase(a, OrdDict1).
      -[{b,2}]
      +

      Erases all items with a specified key from a dictionary.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:erase(a, OrdDict1).
      +[{b,2}]
      @@ -516,11 +516,11 @@

      Returns the value associated with Key in dictionary Orddict. This function assumes that the Key is present in the dictionary. An exception is generated -if Key is not in the dictionary.

      See also section Notes.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:fetch(a, OrdDict1).
      +if Key is not in the dictionary.

      See also section Notes.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:fetch(a, OrdDict1).
       1
      -3> orddict:fetch(missing, OrdDict1).
      +3> orddict:fetch(missing, OrdDict1).
       ** exception error: no function clause matching orddict:fetch(missing,[])
      @@ -549,10 +549,10 @@ -

      Returns a list of all keys in a dictionary.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:fetch_keys(OrdDict1).
      -[a,b]
      +

      Returns a list of all keys in a dictionary.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:fetch_keys(OrdDict1).
      +[a,b]
      @@ -585,10 +585,10 @@

      Orddict2 is a dictionary of all keys and values in Orddict1 for which -Pred(Key, Value) is true.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:filter(fun (K, V) -> V > 1 end, OrdDict1).
      -[{b,2}]
      +Pred(Key, Value) is true.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:filter(fun (K, V) -> V > 1 end, OrdDict1).
      +[{b,2}]
      @@ -618,11 +618,11 @@

      Searches for a key in a dictionary. Returns {ok, Value}, where Value is the value associated with Key, or error if the key is not present in the -dictionary.

      See also section Notes.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:find(a, OrdDict1).
      -{ok,1}
      -3> orddict:find(c, OrdDict1).
      +dictionary.

      See also section Notes.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:find(a, OrdDict1).
      +{ok,1}
      +3> orddict:find(c, OrdDict1).
       error
      @@ -660,10 +660,10 @@

      Calls Fun on successive keys and values of Orddict together with an extra argument Acc (short for accumulator). Fun must return a new accumulator that -is passed to the next call. Acc0 is returned if the list is empty.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:fold(fun (K, V, Acc) -> [{K, V+100} | Acc] end, [], OrdDict1).
      -[{b,102},{a,101}]
      +is passed to the next call. Acc0 is returned if the list is empty.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:fold(fun (K, V, Acc) -> [{K, V+100} | Acc] end, [], OrdDict1).
      +[{b,102},{a,101}]
      @@ -782,10 +782,10 @@

      Calls Fun on successive keys and values of Orddict1 to return a new value -for each key.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> orddict:map(fun (_K, V) -> V + 100 end, OrdDict1).
      -[{a,101},{b,102}]
      +for each key.

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> orddict:map(fun (_K, V) -> V + 100 end, OrdDict1).
      +[{a,101},{b,102}]
      @@ -821,15 +821,15 @@

      Merges two dictionaries, Orddict1 and Orddict2, to create a new dictionary. All the Key-Value pairs from both dictionaries are included in the new dictionary.

      If a key occurs in both dictionaries, Fun is called with the key -and both values to return a new value.

      merge/3 can be defined as follows, but is faster:

      merge(Fun, D1, D2) ->
      -    fold(fun (K, V1, D) ->
      -                 update(K, fun (V2) -> Fun(K, V1, V2) end, V1, D)
      -         end, D2, D1).

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      -[{a,1},{b,2}]
      -2> OrdDict2 = orddict:from_list([{b, 7}, {c, 8}]).
      -[{b,7},{c,8}]
      -3> orddict:merge(fun (K, V1, V2) -> V1 * V2 end, OrdDict1, OrdDict2).
      -[{a,1},{b,14},{c,8}]
      +and both values to return a new value.

      merge/3 can be defined as follows, but is faster:

      merge(Fun, D1, D2) ->
      +    fold(fun (K, V1, D) ->
      +                 update(K, fun (V2) -> Fun(K, V1, V2) end, V1, D)
      +         end, D2, D1).

      Example:

      1> OrdDict1 = orddict:from_list([{a, 1}, {b, 2}]).
      +[{a,1},{b,2}]
      +2> OrdDict2 = orddict:from_list([{b, 7}, {c, 8}]).
      +[{b,7},{c,8}]
      +3> orddict:merge(fun (K, V1, V2) -> V1 * V2 end, OrdDict1, OrdDict2).
      +[{a,1},{b,14},{c,8}]
      /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/ordsets.xhtml differs (HTML document, ASCII text, with very long lines (1517)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/ordsets.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/ordsets.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -342,14 +342,14 @@ -

      Returns a new ordered set formed from Ordset1 with Element inserted.

      Examples

      1> S0 = ordsets:new().
      -[]
      -2> S1 = ordsets:add_element(7, S0).
      -[7]
      -3> S2 = ordsets:add_element(42, S1).
      -[7,42]
      -4> ordsets:add_element(42, S2).
      -[7,42]
      +

      Returns a new ordered set formed from Ordset1 with Element inserted.

      Examples

      1> S0 = ordsets:new().
      +[]
      +2> S1 = ordsets:add_element(7, S0).
      +[7]
      +3> S2 = ordsets:add_element(42, S1).
      +[7,42]
      +4> ordsets:add_element(42, S2).
      +[7,42]
      @@ -378,11 +378,11 @@ -

      Returns a copy of Ordset1 with Element removed.

      Examples

      1> S = ordsets:from_list([a,b,c]).
      -2> ordsets:del_element(c, S).
      -[a,b]
      -3> ordsets:del_element(x, S).
      -[a,b,c]
      +

      Returns a copy of Ordset1 with Element removed.

      Examples

      1> S = ordsets:from_list([a,b,c]).
      +2> ordsets:del_element(c, S).
      +[a,b]
      +3> ordsets:del_element(x, S).
      +[a,b,c]
      @@ -412,10 +412,10 @@ -

      Filters elements in Ordset1 using predicate function Pred.

      Examples

      1> S = ordsets:from_list([1,2,3,4,5,6,7]).
      -2> IsEven = fun(N) -> N rem 2 =:= 0 end.
      -3> ordsets:filter(IsEven, S).
      -[2,4,6]
      +

      Filters elements in Ordset1 using predicate function Pred.

      Examples

      1> S = ordsets:from_list([1,2,3,4,5,6,7]).
      +2> IsEven = fun(N) -> N rem 2 =:= 0 end.
      +3> ordsets:filter(IsEven, S).
      +[2,4,6]
      @@ -452,16 +452,16 @@

      Calls Fun(Elem) for each Elem of Ordset1 to update or remove elements from Ordset1.

      Fun/1 must return either a Boolean or a tuple {true, Value}. The function returns the set of elements for which Fun returns a new -value, with true being equivalent to {true, Elem}.

      ordsets:filtermap/2 behaves as if it were defined as follows:

      filtermap(Fun, Ordset1) ->
      -    ordsets:from_list(lists:filtermap(Fun, Ordset1)).

      Examples

      1> S = ordsets:from_list([2,4,5,6,8,9])
      -2> F = fun(X) ->
      +value, with true being equivalent to {true, Elem}.

      ordsets:filtermap/2 behaves as if it were defined as follows:

      filtermap(Fun, Ordset1) ->
      +    ordsets:from_list(lists:filtermap(Fun, Ordset1)).

      Examples

      1> S = ordsets:from_list([2,4,5,6,8,9])
      +2> F = fun(X) ->
                  case X rem 2 of
      -               0 -> {true, X div 2};
      +               0 -> {true, X div 2};
                      1 -> false
                  end
               end.
      -3> ordsets:filtermap(F, S).
      -[1,2,3,4]
      +3>
      ordsets:filtermap(F, S). +[1,2,3,4]
      @@ -495,9 +495,9 @@

      Folds Function over every element in Ordset and returns the final value of -the accumulator.

      Examples

      1> S = ordsets:from_list([1,2,3,4]).
      +the accumulator.

      Examples

      1> S = ordsets:from_list([1,2,3,4]).
       2> Plus = fun erlang:'+'/2.
      -3> ordsets:fold(Plus, 0, S).
      +3> ordsets:fold(Plus, 0, S).
       10
      @@ -526,8 +526,8 @@ -

      Returns an ordered set of the elements in List.

      Examples

      1> ordsets:from_list([a,b,a,b,b,c]).
      -[a,b,c]
      +

      Returns an ordered set of the elements in List.

      Examples

      1> ordsets:from_list([a,b,a,b,b,c]).
      +[a,b,c]
      @@ -556,15 +556,15 @@

      Returns the intersection of the non-empty list of sets.

      The intersection of multiple sets is a new set that contains only the -elements that are present in all sets.

      Examples

      1> S0 = ordsets:from_list([a,b,c,d]).
      -2> S1 = ordsets:from_list([d,e,f]).
      -3> S2 = ordsets:from_list([q,r])
      -4> Sets = [S0, S1, S2].
      -5> ordsets:intersection([S0, S1, S2]).
      -[]
      -6> ordsets:intersection([S0, S1]).
      -[d]
      -7> ordsets:intersection([]).
      +elements that are present in all sets.

      Examples

      1> S0 = ordsets:from_list([a,b,c,d]).
      +2> S1 = ordsets:from_list([d,e,f]).
      +3> S2 = ordsets:from_list([q,r])
      +4> Sets = [S0, S1, S2].
      +5> ordsets:intersection([S0, S1, S2]).
      +[]
      +6> ordsets:intersection([S0, S1]).
      +[d]
      +7> ordsets:intersection([]).
       ** exception error: no function clause matching ordsets:intersection([])
      @@ -595,13 +595,13 @@

      Returns the intersection of Ordset1 and Ordset2.

      The intersection of two sets is a new set that contains only the -elements that are present in both sets.

      Examples

      1> S0 = ordsets:from_list([a,b,c,d]).
      -2> S1 = ordsets:from_list([c,d,e,f]).
      -3> S2 = ordsets:from_list([q,r]).
      -4> ordsets:intersection(S0, S1).
      -[c,d]
      -5> ordsets:intersection(S1, S2).
      -[]
      +elements that are present in both sets.

      Examples

      1> S0 = ordsets:from_list([a,b,c,d]).
      +2> S1 = ordsets:from_list([c,d,e,f]).
      +3> S2 = ordsets:from_list([q,r]).
      +4> ordsets:intersection(S0, S1).
      +[c,d]
      +5> ordsets:intersection(S1, S2).
      +[]
      @@ -630,12 +630,12 @@

      Returns true if Ordset1 and Ordset2 are disjoint; otherwise, -returns false.

      Two sets are disjoint if they have no elements in common.

      This function is equivalent to ordsets:intersection(Ordset1, Ordset2) =:= [], but faster.

      Examples

      1> S0 = ordsets:from_list([a,b,c,d]).
      -2> S1 = ordsets:from_list([d,e,f]).
      -3> S2 = ordsets:from_list([q,r])
      -4> ordsets:is_disjoint(S0, S1).
      +returns false.

      Two sets are disjoint if they have no elements in common.

      This function is equivalent to ordsets:intersection(Ordset1, Ordset2) =:= [], but faster.

      Examples

      1> S0 = ordsets:from_list([a,b,c,d]).
      +2> S1 = ordsets:from_list([d,e,f]).
      +3> S2 = ordsets:from_list([q,r])
      +4> ordsets:is_disjoint(S0, S1).
       false
      -5> ordsets:is_disjoint(S1, S2).
      +5> ordsets:is_disjoint(S1, S2).
       true
      @@ -664,10 +664,10 @@ -

      Returns true if Element is an element of Ordset; otherwise, returns false.

      Examples

      1> S = ordsets:from_list([a,b,c]).
      -2> ordsets:is_element(42, S).
      +

      Returns true if Element is an element of Ordset; otherwise, returns false.

      Examples

      1> S = ordsets:from_list([a,b,c]).
      +2> ordsets:is_element(42, S).
       false
      -3> ordsets:is_element(b, S).
      +3> ordsets:is_element(b, S).
       true
      @@ -698,9 +698,9 @@ -

      Returns true if Ordset is an empty set; otherwise, returns false.

      Examples

      1> ordsets:is_empty(ordsets:new()).
      +

      Returns true if Ordset is an empty set; otherwise, returns false.

      Examples

      1> ordsets:is_empty(ordsets:new()).
       true
      -2> ordsets:is_empty(ordsets:from_list([1])).
      +2> ordsets:is_empty(ordsets:from_list([1])).
       false
      @@ -732,11 +732,11 @@

      Returns true if Ordset1 and Ordset2 are equal, that is, if every element -of one set is also a member of the other set; otherwise, returns false.

      Examples

      1> Empty = ordsets:new().
      -2> S = ordsets:from_list([a,b]).
      -3> ordsets:is_equal(S, S)
      /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/peer.xhtml differs (HTML document, ASCII text, with very long lines (1109))
      --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/peer.xhtml	2026-08-05 05:56:49.000000000 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/peer.xhtml	2026-08-05 05:56:49.000000000 +0000
      @@ -49,127 +49,127 @@
       manual analysis. If the test case fails, the CRASH REPORT contains these
       arguments
    • multiple test cases can run concurrently speeding up overall testing process, peer node names are unique even when there are multiple instances of the same -test suite running in parallel
    -module(my_SUITE).
    --behaviour(ct_suite).
    --export([all/0, groups/0]).
    --export([basic/1, args/1, named/1, restart_node/1, multi_node/1]).
    +test suite running in parallel
    -module(my_SUITE).
    +-behaviour(ct_suite).
    +-export([all/0, groups/0]).
    +-export([basic/1, args/1, named/1, restart_node/1, multi_node/1]).
     
    --include_lib("common_test/include/ct.hrl").
    +-include_lib("common_test/include/ct.hrl").
     
    -groups() ->
    -    [{quick, [parallel],
    -        [basic, args, named, restart_node, multi_node]}].
    +groups() ->
    +    [{quick, [parallel],
    +        [basic, args, named, restart_node, multi_node]}].
     
    -all() ->
    -    [{group, quick}].
    +all() ->
    +    [{group, quick}].
     
    -basic(Config) when is_list(Config) ->
    -    {ok, Peer, _Node} = ?CT_PEER(),
    -    peer:stop(Peer).
    +basic(Config) when is_list(Config) ->
    +    {ok, Peer, _Node} = ?CT_PEER(),
    +    peer:stop(Peer).
     
    -args(Config) when is_list(Config) ->
    +args(Config) when is_list(Config) ->
         %% specify additional arguments to the new node
    -    {ok, Peer, _Node} = ?CT_PEER(["-emu_flavor", "smp"]),
    -    peer:stop(Peer).
    +    {ok, Peer, _Node} = ?CT_PEER(["-emu_flavor", "smp"]),
    +    peer:stop(Peer).
     
    -named(Config) when is_list(Config) ->
    +named(Config) when is_list(Config) ->
         %% pass test case name down to function starting nodes
    -    Peer = start_node_impl(named_test),
    -    peer:stop(Peer).
    +    Peer = start_node_impl(named_test),
    +    peer:stop(Peer).
     
    -start_node_impl(ActualTestCase) ->
    -    {ok, Peer, Node} = ?CT_PEER(#{name => ?CT_PEER_NAME(ActualTestCase)}),
    +start_node_impl(ActualTestCase) ->
    +    {ok, Peer, Node} = ?CT_PEER(#{name => ?CT_PEER_NAME(ActualTestCase)}),
         %% extra setup needed for multiple test cases
    -    ok = rpc:call(Node, application, set_env, [kernel, key, value]),
    +    ok = rpc:call(Node, application, set_env, [kernel, key, value]),
         Peer.
     
    -restart_node(Config) when is_list(Config) ->
    -    Name = ?CT_PEER_NAME(),
    -    {ok, Peer, Node} = ?CT_PEER(#{name => Name}),
    -    peer:stop(Peer),
    +restart_node(Config) when is_list(Config) ->
    +    Name = ?CT_PEER_NAME(),
    +    {ok, Peer, Node} = ?CT_PEER(#{name => Name}),
    +    peer:stop(Peer),
         %% restart the node with the same name as before
    -    {ok, Peer2, Node} = ?CT_PEER(#{name => Name, args => ["+fnl"]}),
    -    peer:stop(Peer2).

    The next example demonstrates how to start multiple nodes concurrently:

    multi_node(Config) when is_list(Config) ->
    -    Peers = [?CT_PEER(#{wait_boot => {self(), tag}})
    -        || _ <- lists:seq(1, 4)],
    +    {ok, Peer2, Node} = ?CT_PEER(#{name => Name, args => ["+fnl"]}),
    +    peer:stop(Peer2).

    The next example demonstrates how to start multiple nodes concurrently:

    multi_node(Config) when is_list(Config) ->
    +    Peers = [?CT_PEER(#{wait_boot => {self(), tag}})
    +        || _ <- lists:seq(1, 4)],
         %% wait for all nodes to complete boot process, get their names:
    -    _Nodes = [receive {tag, {started, Node, Peer}} -> Node end
    -        || {ok, Peer} <- Peers],
    -    [peer:stop(Peer) || {ok, Peer} <- Peers].

    Start a peer on a different host. Requires ssh key-based authentication set -up, allowing "another_host" connection without password prompt.

    Ssh = os:find_executable("ssh"),
    -peer:start_link(#{exec => {Ssh, ["another_host", "erl"]},
    -    connection => standard_io}),

    The following Common Test case demonstrates Docker integration, starting two + _Nodes = [receive {tag, {started, Node, Peer}} -> Node end + || {ok, Peer} <- Peers], + [peer:stop(Peer) || {ok, Peer} <- Peers].

    Start a peer on a different host. Requires ssh key-based authentication set +up, allowing "another_host" connection without password prompt.

    Ssh = os:find_executable("ssh"),
    +peer:start_link(#{exec => {Ssh, ["another_host", "erl"]},
    +    connection => standard_io}),

    The following Common Test case demonstrates Docker integration, starting two containers with hostnames "one" and "two". In this example Erlang nodes running -inside containers form an Erlang cluster.

    docker(Config) when is_list(Config) ->
    -    Docker = os:find_executable("docker"),
    -    PrivDir = proplists:get_value(priv_dir, Config),
    -    build_release(PrivDir),
    -    build_image(PrivDir),
    +inside containers form an Erlang cluster.

    docker(Config) when is_list(Config) ->
    +    Docker = os:find_executable("docker"),
    +    PrivDir = proplists:get_value(priv_dir, Config),
    +    build_release(PrivDir),
    +    build_image(PrivDir),
     
         %% start two Docker containers
    -    {ok, Peer, Node} = peer:start_link(#{name => lambda,
    +    {ok, Peer, Node} = peer:start_link(#{name => lambda,
             connection => standard_io,
    -        exec => {Docker, ["run", "-h", "one", "-i", "lambda"]}}),
    -    {ok, Peer2, Node2} = peer:start_link(#{name => lambda,
    +        exec => {Docker, ["run", "-h", "one", "-i", "lambda"]}}),
    +    {ok, Peer2, Node2} = peer:start_link(#{name => lambda,
             connection => standard_io,
    -        exec => {Docker, ["run", "-h", "two", "-i", "lambda"]}}),
    +        exec => {Docker, ["run", "-h", "two", "-i", "lambda"]}}),
     
         %% find IP address of the second node using alternative connection RPC
    -    {ok, Ips} = peer:call(Peer2, inet, getifaddrs, []),
    -    {"eth0", Eth0} = lists:keyfind("eth0", 1, Ips),
    -    {addr, Ip} = lists:keyfind(addr, 1, Eth0),
    +    {ok, Ips} = peer:call(Peer2, inet, getifaddrs, []),
    +    {"eth0", Eth0} = lists:keyfind("eth0", 1, Ips),
    +    {addr, Ip} = lists:keyfind(addr, 1, Eth0),
     
         %% make first node to discover second one
    -    ok = peer:call(Peer, inet_db, set_lookup, [[file]]),
    -    ok = peer:call(Peer, inet_db, add_host, [Ip, ["two"]]),
    +    ok = peer:call(Peer, inet_db, set_lookup, [[file]]),
    +    ok = peer:call(Peer, inet_db, add_host, [Ip, ["two"]]),
     
         %% join a cluster
    -    true = peer:call(Peer, net_kernel, connect_node, [Node2]),
    +    true = peer:call(Peer, net_kernel, connect_node, [Node2]),
         %% verify that second peer node has only the first node visible
    -    [Node] = peer:call(Peer2, erlang, nodes, []),
    +    [Node] = peer:call(Peer2, erlang, nodes, []),
     
         %% stop peers, causing containers to also stop
    -    peer:stop(Peer2),
    -    peer:stop(Peer).
    +    peer:stop(Peer2),
    +    peer:stop(Peer).
     
    -build_release(Dir) ->
    +build_release(Dir) ->
         %% load sasl.app file, otherwise application:get_key will fail
    -    application:load(sasl),
    +    application:load(sasl),
         %% create *.rel - release file
    -    RelFile = filename:join(Dir, "lambda.rel"),
    -    Release = {release, {"lambda", "1.0.0"},
    -        {erts, erlang:system_info(version)},
    -        [{App, begin {ok, Vsn} = application:get_key(App, vsn), Vsn end}
    -            || App <- [kernel, stdlib, sasl]]},
    -    ok = file:write_file(RelFile, list_to_binary(lists:flatten(
    -        io_lib:format("~tp.", [Release])))),
    -    RelFileNoExt = filename:join(Dir, "lambda"),
    +    RelFile = filename:join(Dir, "lambda.rel"),
    +    Release = {release, {"lambda", "1.0.0"},
    +        {erts, erlang:system_info(version)},
    +        [{App, begin {ok, Vsn} = application:get_key(App, vsn), Vsn end}
    +            || App <- [kernel, stdlib, sasl]]},
    +    ok = file:write_file(RelFile, list_to_binary(lists:flatten(
    +        io_lib:format("~tp.", [Release])))),
    +    RelFileNoExt = filename:join(Dir, "lambda"),
     
         %% create boot script
    -    {ok, systools_make, []} = systools:make_script(RelFileNoExt,
    -        [silent, {outdir, Dir}]),
    +    {ok, systools_make, []} = systools:make_script(RelFileNoExt,
    +        [silent, {outdir, Dir}]),
         %% package release into *.tar.gz
    -    ok = systools:make_tar(RelFileNoExt, [{erts, code:root_dir()}]).
    +    ok = systools:make_tar(RelFileNoExt, [{erts, code:root_dir()}]).
     
    -build_image(Dir) ->
    +build_image(Dir) ->
         %% Create Dockerfile example, working only for Ubuntu 20.04
         %% Expose port 4445, and make Erlang distribution to listen
         %%  on this port, and connect to it without EPMD
         %% Set cookie on both nodes to be the same.
    -    BuildScript = filename:join(Dir, "Dockerfile"),
    +    BuildScript = filename:join(Dir, "Dockerfile"),
         Dockerfile =
           "FROM ubuntu:20.04 as runner\n"
           "EXPOSE 4445\n"
           "WORKDIR /opt/lambda\n"
           "COPY lambda.tar.gz /tmp\n"
           "RUN tar -zxvf /tmp/lambda.tar.gz -C /opt/lambda\n"
    -      "ENTRYPOINT [\"/opt/lambda/erts-" ++ erlang:system_info(version) ++
    +      "ENTRYPOINT [\"/opt/lambda/erts-" ++ erlang:system_info(version) ++
           "/bin/dyn_erl\", \"-boot\", \"/opt/lambda/releases/1.0.0/start\","
           " \"-kernel\", \"inet_dist_listen_min\", \"4445\","
           " \"-erl_epmd_port\", \"4445\","
           " \"-setcookie\", \"secret\"]\n",
    -    ok = file:write_file(BuildScript, Dockerfile),
    -    os:cmd("docker build -t lambda " ++ Dir).
    +
    ok = file:write_file(BuildScript, Dockerfile), + os:cmd("docker build -t lambda " ++ Dir).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/proc_lib.xhtml differs (HTML document, ASCII text, with very long lines (650)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/proc_lib.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/proc_lib.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -857,21 +857,21 @@ failed. When doing so the start function can return before the failing process has exited, which may block VM resources required for a new start attempt to succeed. Use init_fail/2,3 for that purpose.

    The following example illustrates how this function and proc_lib:start_link/3 -are used:

    -module(my_proc).
    --export([start_link/0]).
    --export([init/1]).
    +are used:

    -module(my_proc).
    +-export([start_link/0]).
    +-export([init/1]).
     
    -start_link() ->
    -    proc_lib:start_link(my_proc, init, [self()]).
    +start_link() ->
    +    proc_lib:start_link(my_proc, init, [self()]).
     
    -init(Parent) ->
    -    case do_initialization() of
    +init(Parent) ->
    +    case do_initialization() of
             ok ->
    -            proc_lib:init_ack(Parent, {ok, self()});
    -        {error, Reason} ->
    -            exit(Reason)
    +            proc_lib:init_ack(Parent, {ok, self()});
    +        {error, Reason} ->
    +            exit(Reason)
         end,
    -    loop().
    +    loop().
     
     ...
    @@ -944,21 +944,21 @@ started process, the start function returns an error tuple when the started process exits, or when the start function time-out (if used) has passed, see start/3,4,5.

    The following example illustrates how this function and proc_lib:start_link/3 -can be used:

    -module(my_proc).
    --export([start_link/0]).
    --export([init/1]).
    +can be used:

    -module(my_proc).
    +-export([start_link/0]).
    +-export([init/1]).
     
    -start_link() ->
    -    proc_lib:start_link(my_proc, init, [self()]).
    +start_link() ->
    +    proc_lib:start_link(my_proc, init, [self()]).
     
    -init(Parent) ->
    -    case do_initialization() of
    +init(Parent) ->
    +    case do_initialization() of
             ok ->
    -            proc_lib:init_ack(Parent, {ok, self()});
    -        {error, Reason} = Error ->
    -            proc_lib:init_fail(Parent, Error, {exit, normal})
    +            proc_lib:init_ack(Parent, {ok, self()});
    +        {error, Reason} = Error ->
    +            proc_lib:init_fail(Parent, Error, {exit, normal})
         end,
    -    loop().
    +    loop().
     
     ...
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/proplists.xhtml differs (HTML document, ASCII text, with very long lines (3915)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/proplists.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/proplists.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -410,7 +410,7 @@

    Similar to get_all_values/2, but each value is wrapped in a list unless it is already itself a list. The resulting list of lists is concatenated. This is -often useful for "incremental" options.

    Example:

    append_values(a, [{a, [1,2]}, {b, 0}, {a, 3}, {c, -1}, {a, [4]}])

    returns:

    [1,2,3,4]
    +often useful for "incremental" options.

    Example:

    append_values(a, [{a, [1,2]}, {b, 0}, {a, 3}, {c, -1}, {a, [4]}])

    returns:

    [1,2,3,4]
    @@ -504,10 +504,10 @@ first entry in ListIn with the same key as Property, and E and Property have equivalent normal forms, then E is replaced with the terms in Expansion, and any following entries with the same key are deleted from -ListIn.

    For example, the following expressions all return [fie, bar, baz, fum]:

    expand([{foo, [bar, baz]}], [fie, foo, fum])
    -expand([{{foo, true}, [bar, baz]}], [fie, foo, fum])
    -expand([{{foo, false}, [bar, baz]}], [fie, {foo, false}, fum])

    However, no expansion is done in the following call because {foo, false} -shadows foo:

    expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])

    Notice that if the original property term is to be preserved in the result when +ListIn.

    For example, the following expressions all return [fie, bar, baz, fum]:

    expand([{foo, [bar, baz]}], [fie, foo, fum])
    +expand([{{foo, true}, [bar, baz]}], [fie, foo, fum])
    +expand([{{foo, false}, [bar, baz]}], [fie, {foo, false}, fum])

    However, no expansion is done in the following call because {foo, false} +shadows foo:

    expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])

    Notice that if the original property term is to be preserved in the result when expanded, it must be included in the expansion list. The inserted terms are not expanded recursively. If Expansions contains more than one property with the same key, only the first occurrence is used.

    See also normalize/2.

    @@ -912,7 +912,7 @@

    Partitions List into a list of sublists and a remainder.

    Lists contains one sublist for each key in Keys, in the corresponding order. The relative order of the elements in each sublist is preserved from the original List. Rest contains the elements in List that are not associated with any of the -specified keys, also with their original relative order preserved.

    Example:

    split([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])

    returns:

    {[[a], [{b, 5}, b],[{c, 2}, {c, 3, 4}]], [{e, 1}, d]}
    +specified keys, also with their original relative order preserved.

    Example:

    split([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])

    returns:

    {[[a], [{b, 5}, b],[{c, 2}, {c, 3, 4}]], [{e, 1}, d]}
    @@ -1035,7 +1035,7 @@ an association of the form Key => Value. Anything else will be silently ignored.

    If the same key appears in List multiple times, the value of the one appearing nearest to the head of List will be in the result map, that is the value that -would be returned by a call to get_value(Key, List).

    Example:

    to_map([a, {b, 1}, {c, 2}, {c, 3}])

    returns:

    #{a => true, b => 1, c => 2}
    +would be returned by a call to get_value(Key, List).

    Example:

    to_map([a, {b, 1}, {c, 2}, {c, 3}])

    returns:

    #{a => true, b => 1, c => 2}
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/qlc.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1572)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/qlc.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/qlc.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -143,24 +143,24 @@ If a tuple {finished} exists among the answers to QH, it is returned twice from append/2.

    As another example, consider concatenating the answers to two queries QH1 and QH2 while removing all duplicates. This is accomplished by using option -unique:

    qlc:q([X || X <- qlc:append(QH1, QH2)], {unique, true})

    The cost is substantial: every returned answer is stored in an ETS table. Before +unique:

    qlc:q([X || X <- qlc:append(QH1, QH2)], {unique, true})

    The cost is substantial: every returned answer is stored in an ETS table. Before returning an answer, it is looked up in the ETS table to check if it has already been returned. Without the unique option, all answers to QH1 would be returned followed by all answers to QH2. The unique option keeps the order between the remaining answers.

    If the order of the answers is not important, there is an alternative to the -unique option, namely to sort the answers uniquely:

    qlc:sort(qlc:q([X || X <- qlc:append(QH1, QH2)], {unique, true})).

    This query also removes duplicates but the answers are sorted. If there are many +unique option, namely to sort the answers uniquely:

    qlc:sort(qlc:q([X || X <- qlc:append(QH1, QH2)], {unique, true})).

    This query also removes duplicates but the answers are sorted. If there are many answers, temporary files are used. Notice that to get the first unique answer, all answers must be found and sorted. Both alternatives find duplicates by comparing answers, that is, if A1 and A2 are answers found in that order, then A2 is a removed if A1 == A2.

    To return only a few answers, cursors can be used. The following code returns no -more than five answers using an ETS table for storing the unique answers:

    C = qlc:cursor(qlc:q([X || X <- qlc:append(QH1, QH2)],{unique,true})),
    -R = qlc:next_answers(C, 5),
    -ok = qlc:delete_cursor(C),
    +more than five answers using an ETS table for storing the unique answers:

    C = qlc:cursor(qlc:q([X || X <- qlc:append(QH1, QH2)],{unique,true})),
    +R = qlc:next_answers(C, 5),
    +ok = qlc:delete_cursor(C),
     R.

    QLCs are convenient for stating constraints on data from two or more tables. The -following example does a natural join on two query handles on position 2:

    qlc:q([{X1,X2,X3,Y1} ||
    -          {X1,X2,X3} <- QH1,
    -          {Y1,Y2} <- QH2,
    -          X2 =:= Y2])

    The qlc module evaluates this differently depending on the query handles QH1 +following example does a natural join on two query handles on position 2:

    qlc:q([{X1,X2,X3,Y1} ||
    +          {X1,X2,X3} <- QH1,
    +          {Y1,Y2} <- QH2,
    +          X2 =:= Y2])

    The qlc module evaluates this differently depending on the query handles QH1 and QH2. If, for example, X2 is matched against the key of a QLC table, the lookup join method traverses the objects of QH2 while looking up key values in the table. However, if not X2 or Y2 is matched against the key or an indexed @@ -168,11 +168,11 @@ both sorted on position 2 and next do the join by traversing the objects one by one.

    Option join can be used to force the qlc module to use a certain join method. For the rest of this section it is assumed that the excessively slow -join method called "nested loop" has been chosen:

    qlc:q([{X1,X2,X3,Y1} ||
    -          {X1,X2,X3} <- QH1,
    -          {Y1,Y2} <- QH2,
    -          X2 =:= Y2],
    -      {join, nested_loop})

    In this case the filter is applied to every possible pair of answers to QH1 +join method called "nested loop" has been chosen:

    qlc:q([{X1,X2,X3,Y1} ||
    +          {X1,X2,X3} <- QH1,
    +          {Y1,Y2} <- QH2,
    +          X2 =:= Y2],
    +      {join, nested_loop})

    In this case the filter is applied to every possible pair of answers to QH1 and QH2, one at a time. If there are M answers to QH1 and N answers to QH2, the filter is run M*N times.

    If QH2 is a call to the function for gb_trees, as defined in section Implementing a QLC Table, then @@ -186,7 +186,7 @@ no side effects so that the meaning of the query does not change if QH2 is evaluated only once. One way of caching the answers is to evaluate QH2 first of all and substitute the list of answers for QH2 in the query. Another way is -to use option cache. It is expressed like this:

    QH2' = qlc:q([X || X <- QH2], {cache, ets})

    or only

    QH2' = qlc:q([X || X <- QH2], cache)

    The effect of option cache is that when generator QH2' is run the first +to use option cache. It is expressed like this:

    QH2' = qlc:q([X || X <- QH2], {cache, ets})

    or only

    QH2' = qlc:q([X || X <- QH2], cache)

    The effect of option cache is that when generator QH2' is run the first time, every answer is stored in an ETS table. When the next answer of QH1 is tried, answers to QH2' are copied from the ETS table, which is very fast. As for option unique the cost is a possibly substantial amount of RAM memory.

    Option {cache, list} offers the possibility to store the answers in a list on @@ -202,62 +202,62 @@ tables and lists on all levels of the query. This can be used for testing if caching would improve efficiency at all. If the answer is yes, further testing is needed to pinpoint the generators that are to be cached.

    Implementing a QLC Table

    As an example of how to use function table/2, the implementation of a QLC -table for the gb_trees module is given:

    -module(gb_table).
    +table for the gb_trees module is given:

    -module(gb_table).
     
    --export([table/1]).
    +-export([table/1]).
     
    -table(T) ->
    -    TF = fun() -> qlc_next(gb_trees:next(gb_trees:iterator(T))) end,
    -    InfoFun = fun(num_of_objects) -> gb_trees:size(T);
    -                 (keypos) -> 1;
    -                 (is_sorted_key) -> true;
    -                 (is_unique_objects) -> true;
    -                 (_) -> undefined
    +table(T) ->
    +    TF = fun() -> qlc_next(gb_trees:next(gb_trees:iterator(T))) end,
    +    InfoFun = fun(num_of_objects) -> gb_trees:size(T);
    +                 (keypos) -> 1;
    +                 (is_sorted_key) -> true;
    +                 (is_unique_objects) -> true;
    +                 (_) -> undefined
                   end,
         LookupFun =
    -        fun(1, Ks) ->
    -                lists:flatmap(fun(K) ->
    -                                      case gb_trees:lookup(K, T) of
    -                                          {value, V} -> [{K,V}];
    -                                          none -> []
    +        fun(1, Ks) ->
    +                lists:flatmap(fun(K) ->
    +                                      case gb_trees:lookup(K, T) of
    +                                          {value, V} -> [{K,V}];
    +                                          none -> []
                                           end
    -                              end, Ks)
    +                              end, Ks)
             end,
         FormatFun =
    -        fun({all, NElements, ElementFun}) ->
    -                ValsS = io_lib:format("gb_trees:from_orddict(~w)",
    -                                      [gb_nodes(T, NElements, ElementFun)]),
    -                io_lib:format("gb_table:table(~s)", [ValsS]);
    -           ({lookup, 1, KeyValues, _NElements, ElementFun}) ->
    -                ValsS = io_lib:format("gb_trees:from_orddict(~w)",
    -                                      [gb_nodes(T, infinity, ElementFun)]),
    -                io_lib:format("lists:flatmap(fun(K) -> "
    +        fun({all, NElements, ElementFun}) ->
    +                ValsS = io_lib:format("gb_trees:from_orddict(~w)",
    +                                      [gb_nodes(T, NElements, ElementFun)]),
    +                io_lib:format("gb_table:table(~s)", [ValsS]);
    +           ({lookup, 1, KeyValues, _NElements, ElementFun}) ->
    +                ValsS = io_lib:format("gb_trees:from_orddict(~w)",
    +                                      [gb_nodes(T, infinity, ElementFun)]),
    +                io_lib:format("lists:flatmap(fun(K) -> "
                                   "case gb_trees:lookup(K, ~s) of "
                                   "{value, V} -> [{K,V}];none -> [] end "
                                   "end, ~w)",
    -                              [ValsS, [ElementFun(KV) || KV <- KeyValues]])
    +                              [ValsS, [ElementFun(KV) || KV <- KeyValues]])
             end,
    -    qlc:table(TF, [{info_fun, InfoFun}, {format_fun, FormatFun},
    -                   {lookup_fun, LookupFun},{key_equality,'=='}]).
    +    qlc:table(TF, [{info_fun, InfoFun}, {format_fun, FormatFun},
    +                   {lookup_fun, LookupFun},{key_equality,'=='}]).
     
    -qlc_next({X, V, S}) ->
    -    [{X,V} | fun() -> qlc_next(gb_trees:next(S)) end];
    -qlc_next(none) ->
    -    [].
    -
    -gb_nodes(T, infinity, ElementFun) ->
    -    gb_nodes(T, -1, ElementFun);
    -gb_nodes(T, NElements, ElementFun) ->
    -    gb_iter(gb_trees:iterator(T), NElements, ElementFun).
    +qlc_next({X, V, S}) ->
    +    [{X,V} | fun() -> qlc_next(gb_trees:next(S)) end];
    +qlc_next(none) ->
    +    [].
    +
    +gb_nodes(T, infinity, ElementFun) ->
    +    gb_nodes(T, -1, ElementFun);
    +gb_nodes(T, NElements, ElementFun) ->
    +    gb_iter(gb_trees:iterator(T), NElements, ElementFun).
     
    -gb_iter(_I, 0, _EFun) ->
    +gb_iter(_I, 0, _EFun) ->
         '...';
    -gb_iter(I0, N, EFun) ->
    -    case gb_trees:next(I0) of
    -        {X, V, I} ->
    -            [EFun({X,V}) | gb_iter(I, N-1, EFun)];
    +gb_iter(I0, N, EFun) ->
    +    case gb_trees:next(I0) of
    +        {X, V, I} ->
    +            [EFun({X,V}) | gb_iter(I, N-1, EFun)];
             none ->
    -            []
    +            []
         end.

    TF is the traversal function. The qlc module requires that there is a way of traversing all objects of the data structure. gb_trees has an iterator function suitable for that purpose. Notice that for each object returned, a new @@ -287,49 +287,49 @@ example, 2 == 2.0 evaluates to true while 2 =:= 2.0 evaluates to false. Normally this is a minor issue, but the qlc module cannot ignore the difference, which affects the user's choice of operators in QLCs.

    If the qlc module at compile time can determine that some constant is free of -integers, it does not matter which one of ==/2 or =:=/2 is used:

    1> E1 = ets:new(t, [set]), % uses =:=/2 for key equality
    -Q1 = qlc:q([K ||
    -{K} <- ets:table(E1),
    -K == 2.71 orelse K == a]),
    -io:format("~s~n", [qlc:info(Q1)]).
    -ets:match_spec_run(
    -       lists:flatmap(fun(V) ->
    -			    ets:lookup(#Ref<0.3098908599.2283929601.256025>,
    -				       V)
    +integers, it does not matter which one of ==/2 or =:=/2 is used:

    1> E1 = ets:new(t, [set]), % uses =:=/2 for key equality
    +Q1 = qlc:q([K ||
    +{K} <- ets:table(E1),
    +K == 2.71 orelse K == a]),
    +io:format("~s~n", [qlc:info(Q1)]).
    +ets:match_spec_run(
    +       lists:flatmap(fun(V) ->
    +			    ets:lookup(#Ref<0.3098908599.2283929601.256025>,
    +				       V)
     		     end,
    -		     [a, 2.71]),
    -       ets:match_spec_compile([{{'$1'}, [], ['$1']}]))

    In the example, operator ==/2 has been handled exactly as =:=/2 would have + [a, 2.71]), + ets:match_spec_compile([{{'$1'}, [], ['$1']}]))

    In the example, operator ==/2 has been handled exactly as =:=/2 would have been handled. However, if it cannot be determined at compile time that some constant is free of integers, and the table uses =:=/2 when comparing keys for equality (see option key_equality), then the qlc module does not try to look up the constant. The reason is that there is in the general case no upper limit on the number of key values that can compare equal -to such a constant; every combination of integers and floats must be looked up:

    2> E2 = ets:new(t, [set]),
    -true = ets:insert(E2, [{{2,2},a},{{2,2.0},b},{{2.0,2},c}]),
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/queue.xhtml differs (HTML document, ASCII text, with very long lines (1100))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/queue.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/queue.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -598,12 +598,12 @@
     
           
     
    -

    Returns a queue Q2 that is the result of removing the front item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:from_list([1,2,3,4,5]).
    -{[5,4,3],[1,2]}
    -2> Queue = queue:drop(Queue).
    -{[5,4,3],[2]}
    -3> queue:to_list(Queue1).
    -[2,3,4,5]
    +

    Returns a queue Q2 that is the result of removing the front item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:from_list([1,2,3,4,5]).
    +{[5,4,3],[1,2]}
    +2> Queue = queue:drop(Queue).
    +{[5,4,3],[2]}
    +3> queue:to_list(Queue1).
    +[2,3,4,5]
    @@ -631,12 +631,12 @@ -

    Returns a queue Q2 that is the result of removing the rear item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:from_list([1,2,3,4,5]).
    -{[5,4,3],[1,2]}
    -2> Queue = queue:drop_r(Queue).
    -{[4,3],[1,2]}
    -3> queue:to_list(Queue1).
    -[1,2,3,4]
    +

    Returns a queue Q2 that is the result of removing the rear item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:from_list([1,2,3,4,5]).
    +{[5,4,3],[1,2]}
    +2> Queue = queue:drop_r(Queue).
    +{[4,3],[1,2]}
    +3> queue:to_list(Queue1).
    +[1,2,3,4]
    @@ -664,9 +664,9 @@ -

    Returns Item at the front of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> Queue = queue:from_list([1,2,3,4,5]).
    -{[5,4,3],[1,2]}
    -2> 1 == queue:get(Queue).
    +

    Returns Item at the front of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> Queue = queue:from_list([1,2,3,4,5]).
    +{[5,4,3],[1,2]}
    +2> 1 == queue:get(Queue).
     true
    @@ -695,9 +695,9 @@ -

    Returns Item at the rear of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> Queue = queue:from_list([1,2,3,4,5]).
    -{[5,4,3],[1,2]}
    -2> 5 == queue:get_r(Queue).
    +

    Returns Item at the rear of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> Queue = queue:from_list([1,2,3,4,5]).
    +{[5,4,3],[1,2]}
    +2> 5 == queue:get_r(Queue).
     true
    @@ -727,12 +727,12 @@

    Returns tuple {value, Item}, where Item is the front item of Q, or empty -if Q is empty.

    Example 1:

    1> queue:peek(queue:new()).
    +if Q is empty.

    Example 1:

    1> queue:peek(queue:new()).
     empty
    -2> Queue = queue:from_list([1,2,3,4,5]).
    -{[5,4,3],[1,2]}
    -3> queue:peek(Queue).
    -{value, 1}
    +2>
    Queue = queue:from_list([1,2,3,4,5]). +{[5,4,3],[1,2]} +3> queue:peek(Queue). +{value, 1}
    @@ -761,12 +761,12 @@

    Returns tuple {value, Item}, where Item is the rear item of Q, or empty -if Q is empty.

    Example 1:

    1> queue:peek_r(queue:new()).
    +if Q is empty.

    Example 1:

    1> queue:peek_r(queue:new()).
     empty
    -2> Queue = queue:from_list([1,2,3,4,5]).
    -{[5,4,3],[1,2]}
    -3> queue:peek_r(Queue).
    -{value, 5}
    +2>
    Queue = queue:from_list([1,2,3,4,5]). +{[5,4,3],[1,2]} +3> queue:peek_r(Queue). +{value, 5}
    @@ -801,10 +801,10 @@ -

    Inserts Item at the head of queue Q1. Returns the new queue Q2.

    Example:

    1> Queue = queue:cons(0, queue:from_list([1,2,3])).
    -{[3,2],[0,1]}
    -2> queue:to_list(Queue).
    -[0,1,2,3]
    +

    Inserts Item at the head of queue Q1. Returns the new queue Q2.

    Example:

    1> Queue = queue:cons(0, queue:from_list([1,2,3])).
    +{[3,2],[0,1]}
    +2> queue:to_list(Queue).
    +[0,1,2,3]
    @@ -832,7 +832,7 @@ -

    Returns the tail item of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> queue:daeh(queue:from_list([1,2,3])).
    +

    Returns the tail item of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> queue:daeh(queue:from_list([1,2,3])).
     3
    @@ -861,7 +861,7 @@ -

    Returns Item from the head of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> queue:head(queue:from_list([1,2,3])).
    +

    Returns Item from the head of queue Q.

    Fails with reason empty if Q is empty.

    Example 1:

    1> queue:head(queue:from_list([1,2,3])).
     1
    @@ -890,10 +890,10 @@ -

    Returns a queue Q2 that is the result of removing the tail item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:init(queue:from_list([1,2,3])).
    -{[2],[1]}
    -2> queue:to_list(Queue).
    -[1,2]
    +

    Returns a queue Q2 that is the result of removing the tail item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:init(queue:from_list([1,2,3])).
    +{[2],[1]}
    +2> queue:to_list(Queue).
    +[1,2]
    @@ -953,7 +953,7 @@ -

    Returns the tail item of queue Q.

    Fails with reason empty if Q is empty.

    Example:

    1> queue:last(queue:from_list([1,2,3])).
    +

    Returns the tail item of queue Q.

    Fails with reason empty if Q is empty.

    Example:

    1> queue:last(queue:from_list([1,2,3])).
     3
    @@ -982,10 +982,10 @@ -

    Returns a queue Q2 that is the result of removing the tail item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:liat(queue:from_list([1,2,3])).
    -{[2],[1]}
    -2> queue:to_list(Queue).
    -[1,2]
    +

    Returns a queue Q2 that is the result of removing the tail item from Q1.

    Fails with reason empty if Q1 is empty.

    Example:

    1> Queue = queue:liat(queue:from_list([1,2,3])).
    +{[2],[1]}
    +2> queue:to_list(Queue).
    +[1,2]
    @@ -1013,10 +1013,10 @@ -

    Inserts Item as the tail item of queue Q1. Returns the new queue Q2.

    Example:

    1> Queue = queue:snoc(queue:from_list([1,2,3]), 4).
    -{[4,3,2],[1]}
    -2> queue:to_list(Queue).
    -[1,2,3,4]
    +

    Inserts Item as the tail item of queue Q1. Returns the new queue Q2.

    Example:

    1> Queue = queue:snoc(queue:from_list([1,2,3]), 4).
    +{[4,3,2],[1]}
    +2> queue:to_list(Queue).
    +[1,2,3,4]
    @@ -1082,10 +1082,10 @@

    Returns true if Pred(Item) returns true for all items Item in Q, -otherwise false.

    Example:

    1> Queue = queue:from_list([1,2,3,4,5]).
    -2> queue:all(fun (E) -> E > 3 end, Queue).
    +otherwise false.

    Example:

    1> Queue = queue:from_list([1,2,3,4,5]).
    +2> queue:all(fun (E) -> E > 3 end, Queue).
     false
    -3> queue:all(fun (E) -> E > 0 end, Queue).
    +3> queue:all(fun (E) -> E > 0 end, Queue).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/random.xhtml differs (HTML document, ASCII text, with very long lines (756))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/random.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/random.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -344,9 +344,9 @@
           
     
     

    Seeds random number generation with integer values in the process dictionary and -returns the old state.

    The following is an easy way of obtaining a unique value to seed with:

    random:seed(erlang:phash2([node()]),
    -            erlang:monotonic_time(),
    -            erlang:unique_integer())

    For details, see erlang:phash2/1, erlang:node/0, erlang:monotonic_time/0, +returns the old state.

    The following is an easy way of obtaining a unique value to seed with:

    random:seed(erlang:phash2([node()]),
    +            erlang:monotonic_time(),
    +            erlang:unique_integer())

    For details, see erlang:phash2/1, erlang:node/0, erlang:monotonic_time/0, and erlang:unique_integer/0.

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/rand.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (2577)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/rand.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/rand.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -83,40 +83,40 @@
    %% If there is no state there, [`seed(default)`](`seed/1`) %% is implicitly called first: %% -1> R0 = rand:uniform(), - is_float(R0) andalso 0.0 =< R0 andalso R0 < 1.0. +1> R0 = rand:uniform(), + is_float(R0) andalso 0.0 =< R0 andalso R0 < 1.0. true -2> R1 = rand:uniform(), - is_float(R1) andalso 0.0 =< R1 andalso R1 < 1.0. +2> R1 = rand:uniform(), + is_float(R1) andalso 0.0 =< R1 andalso R1 < 1.0. true %% Generate a uniformly distributed integer in the range 1..4711: %% -3> K0 = rand:uniform(4711), - is_integer(K0) andalso 1 =< K0 andalso K0 =< 4711. +3> K0 = rand:uniform(4711), + is_integer(K0) andalso 1 =< K0 andalso K0 =< 4711. true %% Generate a binary with 16 bytes, uniformly distributed: %% -4> B0 = rand:bytes(16), - byte_size(B0) == 16. +4> B0 = rand:bytes(16), + byte_size(B0) == 16. true %% Select and initialize a specified algorithm, %% with an automatic default seed, then generate %% a floating point number: %% -5> rand:seed(exro928ss). -6> R2 = rand:uniform(), - is_float(R2) andalso 0.0 =< R2 andalso R2 < 1.0. +5> rand:seed(exro928ss). +6> R2 = rand:uniform(), + is_float(R2) andalso 0.0 =< R2 andalso R2 < 1.0. true %% Select and initialize a specified algorithm %% with a specified seed, then generate %% a floating point number: %% -7> rand:seed(exro928ss, 123456789). -8> R3 = rand:uniform(). +7> rand:seed(exro928ss, 123456789). +8> R3 = rand:uniform(). 0.48303622772415256 %% Select and initialize a specific algorithm, @@ -124,28 +124,28 @@ %% with explicit generator state, then generate %% two floating point numbers. %% -9> S0 = rand:seed_s(exsss). -10> {R4, S1} = rand:uniform_s(S0), - is_float(R4) andalso 0.0 =< R4 andalso R4 < 1.0. +9> S0 = rand:seed_s(exsss). +10> {R4, S1} = rand:uniform_s(S0), + is_float(R4) andalso 0.0 =< R4 andalso R4 < 1.0. true -11> {R5, S2} = rand:uniform_s(S1), - is_float(R5) andalso 0.0 =< R5 andalso R5 < 1.0. +11> {R5, S2} = rand:uniform_s(S1), + is_float(R5) andalso 0.0 =< R5 andalso R5 < 1.0. true %% Repeat the first after seed -12> {R4, _} = rand:uniform_s(S0). +12> {R4, _} = rand:uniform_s(S0). %% Generate a standard normal distribution number %% using the built-in fast Ziggurat Method: %% -13> {SND0, S3} = rand:normal_s(S2), - is_float(SND0). +13> {SND0, S3} = rand:normal_s(S2), + is_float(SND0). true %% Generate a normal distribution number %% with mean -3 and variance 0.5: %% -14> {ND0, S4} = rand:normal_s(-3, 0.5, S3), - is_float(ND0). +14> {ND0, S4} = rand:normal_s(-3, 0.5, S3), + is_float(ND0). true %% Generate a textbook basic form Box-Muller @@ -153,14 +153,14 @@ %% distribution as the built-in Ziggurat method above, %% but is much slower: %% -15> R6 = rand:uniform_real(), - is_float(R6) andalso 0.0 < R6 andalso R6 < 1.0. +15> R6 = rand:uniform_real(), + is_float(R6) andalso 0.0 < R6 andalso R6 < 1.0. true -16> R7 = rand:uniform(), - is_float(R7) andalso 0.0 =< R7 andalso R7 < 1.0. +16> R7 = rand:uniform(), + is_float(R7) andalso 0.0 =< R7 andalso R7 < 1.0. true %% R6 cannot be equal to 0.0 so math:log/1 will never fail -17> SND1 = math:sqrt(-2 * math:log(R6)) * math:cos(math:pi() * R7).

    Algorithms

    The base generator algorithms implement the +17> SND1 = math:sqrt(-2 * math:log(R6)) * math:cos(math:pi() * R7).

    Algorithms

    The base generator algorithms implement the Xoroshiro and Xorshift algorithms by Sebastiano Vigna. During an iteration they generate an integer (at least 58-bit) and operate on a state of several integers. @@ -227,7 +227,7 @@ up to (and included) 16TB, with the exception of binary rank tests, which fail due to the lowest bit being an LFSR; all other bits pass all tests. We suggest to use a sign test to extract a random Boolean value.

    If this is a problem; to generate a boolean with these algorithms, -use something like this:

    (rand:uniform(256) > 128) % -> boolean()
    ((rand:uniform(256) - 1) bsr 7) % -> 0 | 1

    For a general range, with N = 1 for exrop, and N = 3 for exs1024s:

    (((rand:uniform(Range bsl N) - 1) bsr N) + 1)

    The floating point generating functions in this module waste the lowest bits +use something like this:

    (rand:uniform(256) > 128) % -> boolean()
    ((rand:uniform(256) - 1) bsr 7) % -> 0 | 1

    For a general range, with N = 1 for exrop, and N = 3 for exs1024s:

    (((rand:uniform(Range bsl N) - 1) bsr N) + 1)

    The floating point generating functions in this module waste the lowest bits when converting from an integer so they avoid this snag.

    Niche algorithms

    The niche algorithms API contains special purpose algorithms that do not use the plug-in framework, mainly for performance reasons.

    Since these algorithms lack the plug-in framework support, generating numbers @@ -1421,7 +1421,7 @@ 16#7fa6502 * 2^32 - 1, which have been selected, in collaboration with Sebastiano Vigna, to avoid bignum operations and still get good statistical quality. It has been named "MWC59" and can be written as:

    C = CX0 bsr 32
    -X = CX0 band ((1 bsl 32)-1))
    +X = CX0 band ((1 bsl 32)-1))
     CX1 = 16#7fa6502 * X + C

    Because the generator uses a multiplier that is a power of 2 it gets statistical flaws for collision tests and birthday spacings tests in 2 and 3 dimensions, and these caveats apply even when looking @@ -2324,10 +2324,10 @@ equally spaced in the interval.

    Warning

    This function may return exactly 0.0 which can be fatal for certain applications. If that is undesired you can use (1.0 - rand:uniform()) to get the interval 0.0 < X =< 1.0, or instead use uniform_real/0.

    If neither endpoint is desired you can achieve the range -0.0 < X < 1.0 using test and re-try like this:

    my_uniform() ->
    -    case rand:uniform() of
    +0.0 < X < 1.0 using test and re-try like this:

    my_uniform() ->
    +    case rand:uniform() of
             X when 0.0 < X -> X;
    -        _ -> my_uniform()
    +        _ -> my_uniform()
         end.
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/re.xhtml differs (HTML document, ASCII text, with very long lines (2087)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/re.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/re.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -2405,32 +2405,32 @@

    Takes a compiled regular expression and an item, and returns the relevant data from the regular expression.

    The only supported item is namelist, which returns the tuple {namelist, [binary()]}, -containing the names of all (unique) named subpatterns in the regular expression.

    For example:

    1> {ok,MP} = re:compile("(?<A>A)|(?<B>B)|(?<C>C)").
    -{ok,{re_pattern,3,0,0,
    -                <<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,
    -                  255,255,...>>}}
    -2> re:inspect(MP,namelist).
    -{namelist,[<<"A">>,<<"B">>,<<"C">>]}
    -3> {ok,MPD} = re:compile("(?<C>A)|(?<B>B)|(?<C>C)",[dupnames]).
    -{ok,{re_pattern,3,0,0,
    -                <<69,82,67,80,119,0,0,0,0,0,8,0,1,0,0,0,255,255,255,255,
    -                  255,255,...>>}}
    -4> re:inspect(MPD,namelist).
    -{namelist,[<<"B">>,<<"C">>]}

    Notice in the second example that the duplicate name only occurs once in the +containing the names of all (unique) named subpatterns in the regular expression.

    For example:

    1> {ok,MP} = re:compile("(?<A>A)|(?<B>B)|(?<C>C)").
    +{ok,{re_pattern,3,0,0,
    +                <<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,
    +                  255,255,...>>}}
    +2> re:inspect(MP,namelist).
    +{namelist,[<<"A">>,<<"B">>,<<"C">>]}
    +3> {ok,MPD} = re:compile("(?<C>A)|(?<B>B)|(?<C>C)",[dupnames]).
    +{ok,{re_pattern,3,0,0,
    +                <<69,82,67,80,119,0,0,0,0,0,8,0,1,0,0,0,255,255,255,255,
    +                  255,255,...>>}}
    +4> re:inspect(MPD,namelist).
    +{namelist,[<<"B">>,<<"C">>]}

    Notice in the second example that the duplicate name only occurs once in the returned list, and that the list is in alphabetical order regardless of where the names are positioned in the regular expression. The order of the names is the same as the order of captured subexpressions if {capture, all_names} is specified as an option to run/3. You can therefore create a name-to-value -mapping from the result of run/3 like this:

    1> {ok,MP} = re:compile("(?<A>A)|(?<B>B)|(?<C>C)").
    -{ok,{re_pattern,3,0,0,
    -                <<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,
    -                  255,255,...>>}}
    -2> {namelist, N} = re:inspect(MP,namelist).
    -{namelist,[<<"A">>,<<"B">>,<<"C">>]}
    -3> {match,L} = re:run("AA",MP,[{capture,all_names,binary}]).
    -{match,[<<"A">>,<<>>,<<>>]}
    -4> NameMap = lists:zip(N,L).
    -[{<<"A">>,<<"A">>},{<<"B">>,<<>>},{<<"C">>,<<>>}]
    +mapping from the result of run/3 like this:

    1> {ok,MP} = re:compile("(?<A>A)|(?<B>B)|(?<C>C)").
    +{ok,{re_pattern,3,0,0,
    +                <<69,82,67,80,119,0,0,0,0,0,0,0,1,0,0,0,255,255,255,255,
    +                  255,255,...>>}}
    +2> {namelist, N} = re:inspect(MP,namelist).
    +{namelist,[<<"A">>,<<"B">>,<<"C">>]}
    +3> {match,L} = re:run("AA",MP,[{capture,all_names,binary}]).
    +{match,[<<"A">>,<<>>,<<>>]}
    +4> NameMap = lists:zip(N,L).
    +[{<<"A">>,<<"A">>},{<<"B">>,<<>>},{<<"C">>,<<>>}]
    @@ -2519,16 +2519,16 @@ subexpression number N, is inserted in the result. If no subexpression with that number is generated by the regular expression, nothing is inserted.

    To insert an & or a \ in the result, precede it with a \. Notice that Erlang already gives a special meaning to \ in literal strings, so a single \ must be -written as "\\" and therefore a double \ as "\\\\".

    Example:

    1> re:replace("abcd","c","[&]",[{return,list}]).
    -"ab[c]d"

    while

    2> re:replace("abcd","c","[\\&]",[{return,list}]).
    +written as "\\" and therefore a double \ as "\\\\".

    Example:

    1> re:replace("abcd","c","[&]",[{return,list}]).
    +"ab[c]d"

    while

    2> re:replace("abcd","c","[\\&]",[{return,list}]).
     "ab[&]d"

    If the replacement is given as a fun, it will be called with the whole matching expression as the first argument and a list of subexpression matches in the order in which they appear in the regular expression. The returned value will be -inserted in the result.

    Example:

    3> re:replace("abcd", ".(.)",
    -    fun(Whole, [<<C>>]) ->
    -         <<$#, Whole/binary, $-, (C - $a + $A), $#>>
    +inserted in the result.

    Example:

    3> re:replace("abcd", ".(.)",
    +    fun(Whole, [<<C>>]) ->
    +         <<$#, Whole/binary, $-, (C - $a + $A), $#>>
         end,
    -    [{return, list}]).
    +    [{return, list}]).
     "#ab-B#cd"

    Note

    Non-matching optional subexpressions will not be included in the list of subexpression matches if they are the last subexpressions in the regular expression.

    Example:

    The regular expression "(a)(b)?(c)?" ("a", optionally followed by "b", @@ -2649,7 +2649,7 @@ run/3 handles empty matches in the same way as Perl: a zero-length match at any point is also retried with options [anchored, notempty_atstart]. If that search gives a result of length > 0, -the result is included. Example:

    re:run("cat","(|at)",[global]).

    The following matchings are performed:

    • At offset 0 - The regular expression (|at) first match at the +the result is included. Example:

      re:run("cat","(|at)",[global]).

      The following matchings are performed:

      • At offset 0 - The regular expression (|at) first match at the initial position of string cat, giving the result set [{0,0},{0,0}] (the second {0,0} is because of the subexpression marked by the parentheses). As the length of the match is 0, we do not advance to the next position yet.

      • At offset 0 with [anchored, notempty_atstart] - The search is @@ -2661,7 +2661,7 @@ of results and the position in the search string is advanced two steps.

      • At offset 3 - The search once again matches the empty string, giving [{3,0},{3,0}].

      • At offset 1 with [anchored, notempty_atstart] - This gives no result of length > 0 and we are at the last position, so the global search is -complete.

      The result of the call is:

      {match,[[{0,0},{0,0}],[{1,0},{1,0}],[{1,2},{1,2}],[{3,0},{3,0}]]}
    • notempty - An empty string is not considered to be a valid match if this +complete.

    The result of the call is:

    {match,[[{0,0},{0,0}],[{1,0},{1,0}],[{1,2},{1,2}],[{3,0},{3,0}]]}
  • notempty - An empty string is not considered to be a valid match if this option is specified. If alternatives in the pattern exist, they are tried. If all the alternatives match the empty string, the entire match fails.

    Example:

    If the following pattern is applied to a string not beginning with "a" or "b", it would normally match the empty string at the start of the subject:

    a?b?

    With option notempty, this match is invalid, so run/3 searches @@ -2732,12 +2732,12 @@ instead of the stack, the amount of heap memory that can be used.

    The Erlang VM uses a PCRE library where heap memory is used when regular expression match recursion occurs. This therefore limits the use of machine heap, not C stack.

    Specifying a lower value can result in matches with deep recursion failing, -when they should have matched:

    1> re:run("aaaaaaaaaaaaaz","(a+)*z").
    -{match,[{0,14},{0,13}]}
    -2> re:run("aaaaaaaaaaaaaz","(a+)*z",[{match_limit_recursion,5}]).
    +when they should have matched:

    1> re:run("aaaaaaaaaaaaaz","(a+)*z").
    +{match,[{0,14},{0,13}]}
    +2> re:run("aaaaaaaaaaaaaz","(a+)*z",[{match_limit_recursion,5}]).
     nomatch
    -3> re:run("aaaaaaaaaaaaaz","(a+)*z",[{match_limit_recursion,5},report_errors]).
    -{error,match_limit_recursion}

    This option and option match_limit are only to be used in rare cases. +3> re:run("aaaaaaaaaaaaaz","(a+)*z",[{match_limit_recursion,5},report_errors]). +{error,match_limit_recursion}

    This option and option match_limit are only to be used in rare cases. Understanding of the PCRE library internals is recommended before tampering with these limits.

  • {offset, integer() >= 0} - Start matching at the offset (position) specified in the subject string. The offset is zero-based, so that the default @@ -2750,9 +2750,9 @@ capturing).

    As an example of the default behavior, the following call returns, as first and only captured string, the matching part of the subject ("abcd" in the middle) as an index pair {3,4}, where character positions are zero-based, -just as in offsets:

    re:run("ABCabcdABC","abcd",[]).

    The return value of this call is:

    {match,[{3,4}]}

    Another (and quite common) case is where the regular expression matches all of -the subject:

    re:run("ABCabcdABC",".*abcd.*",[]).

    Here the return value correspondingly points out all of the string, beginning -at index 0, and it is 10 characters long:

    {match,[{0,10}]}

    If the regular expression contains capturing subpatterns, like in:

    re:run("ABCabcdABC",".*(abcd).*",[]).

    all of the matched subject is captured, as well as the captured substrings:

    {match,[{0,10},{3,4}]}

    The complete matching pattern always gives the first return value in the list +just as in offsets:

    re:run("ABCabcdABC","abcd",[]).

    The return value of this call is:

    {match,[{3,4}]}

    Another (and quite common) case is where the regular expression matches all of +the subject:

    re:run("ABCabcdABC",".*abcd.*",[]).

    Here the return value correspondingly points out all of the string, beginning +at index 0, and it is 10 characters long:

    {match,[{0,10}]}

    If the regular expression contains capturing subpatterns, like in:

    re:run("ABCabcdABC",".*(abcd).*",[]).

    all of the matched subject is captured, as well as the captured substrings:

    {match,[{0,10},{3,4}]}

    The complete matching pattern always gives the first return value in the list and the remaining subpatterns are added in the order they occurred in the regular expression.

    The capture tuple is built up as follows:

    • ValueSpec - Specifies which captured (sub)patterns are to be returned. ValueSpec can either be an atom describing a predefined set of return @@ -2777,12 +2777,12 @@ subpatterns (see below) in the regular expression, one can use atom/0s or string/0s to specify the subpatterns to be returned. For example, consider the regular expression:

      ".*(abcd).*"

      matched against string "ABCabcdABC", capturing only the "abcd" part (the -first explicit subpattern):

      re:run("ABCabcdABC",".*(abcd).*",[{capture,[1]}]).

      The call gives the following result, as the first explicitly captured +first explicit subpattern):

      re:run("ABCabcdABC",".*(abcd).*",[{capture,[1]}]).

      The call gives the following result, as the first explicitly captured subpattern is "(abcd)", matching "abcd" in the subject, at (zero-based) -position 3, of length 4:

      {match,[{3,4}]}

      Consider the same regular expression, but with the subpattern explicitly +position 3, of length 4:

      {match,[{3,4}]}

      Consider the same regular expression, but with the subpattern explicitly named 'FOO':

      ".*(?<FOO>abcd).*"

      With this expression, we could still give the index of the subpattern with -the following call:

      re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,[1]}]).

      giving the same result as before. But, as the subpattern is named, we can -also specify its name in the value list:

      re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,['FOO']}]).

      This would give the same result as the earlier examples, namely:

      {match,[{3,4}]}

      The values list can specify indexes or names not present in the regular +the following call:

      re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,[1]}]).

      giving the same result as before. But, as the subpattern is named, we can +also specify its name in the value list:

      re:run("ABCabcdABC",".*(?<FOO>abcd).*",[{capture,['FOO']}]).

      This would give the same result as the earlier examples, namely:

      {match,[{3,4}]}

      The values list can specify indexes or names not present in the regular expression, in which case the return values vary depending on the type. If the type is index, the tuple {-1,0} is returned for values with no corresponding subpattern in the regular expression, but for the other types @@ -2817,12 +2817,12 @@ string:

      "ABCabcdABC"

      the subpattern at index 2 does not match, as "abdd" is not present in the string, but the complete pattern matches (because of the alternative a(..d)). The subpattern at index 2 is therefore unassigned and the default -return value is:

      {match,[{0,10},{3,4},{-1,0},{4,3}]}

      Setting the capture Type to binary gives:

      {match,[<<"ABCabcdABC">>,<<"abcd">>,<<>>,<<"bcd">>]}

      Here the empty binary (<<>>) represents the unassigned subpattern. In the +return value is:

      {match,[{0,10},{3,4},{-1,0},{4,3}]}

      Setting the capture Type to binary gives:

      {match,[<<"ABCabcdABC">>,<<"abcd">>,<<>>,<<"bcd">>]}

      Here the empty binary (<<>>) represents the unassigned subpattern. In the binary case, some information about the matching is therefore lost, as <<>> can also be an empty string captured.

      If differentiation between empty matches and non-existing subpatterns is necessary, use the type index and do the conversion to the final type in Erlang code.

      When option global is speciified, the capture specification affects each -match separately, so that:

      re:run("cacb","c(a|b)",[global,{capture,[1],list}]).

      gives

      {match,[["a"],["b"]]}

    For a descriptions of options only affecting the compilation step, see +match separately, so that:

    re:run("cacb","c(a|b)",[global,{capture,[1],list}]).

    gives

    {match,[["a"],["b"]]}
  • For a descriptions of options only affecting the compilation step, see compile/2.

    @@ -2909,7 +2909,7 @@ compilation option is specified to this function, both the regular expression and Subject are to be specified as valid Unicode charlist()s.

    The result is given as a list of "strings", the preferred data type specified in option return (default iodata).

    If subexpressions are specified in the regular expression, the matching -subexpressions are returned in the resulting list as well. For example:

    re:split("Erlang","[ln]",[{return,list}]).

    gives

    ["Er","a","g"]

    while

    re:split("Erlang","([ln])",[{return,list}]).

    gives

    ["Er","l","a","n","g"]

    The text matching the subexpression (marked by the parentheses in the regular +subexpressions are returned in the resulting list as well. For example:

    re:split("Erlang","[ln]",[{return,list}]).

    gives

    ["Er","a","g"]

    while

    re:split("Erlang","([ln])",[{return,list}]).

    gives

    ["Er","l","a","n","g"]

    The text matching the subexpression (marked by the parentheses in the regular expression) is inserted in the result list where it was found. This means that concatenating the result of a split where the whole regular expression is a single subexpression (as in the last example) always results in the original @@ -2917,21 +2917,21 @@ "g"), nothing is inserted after that. To make the group of strings and the parts matching the subexpressions more obvious, one can use option group, which groups together the part of the subject string with the parts matching the -subexpressions when the string was split:

    re:split("Erlang","([ln])",[{return,list},group]).

    gives

    [["Er","l"],["a","n"],["g"]]

    Here the regular expression first matched the "l", causing "Er" to be the first +subexpressions when the string was split:

    re:split("Erlang","([ln])",[{return,list},group]).

    gives

    [["Er","l"],["a","n"],["g"]]

    Here the regular expression first matched the "l", causing "Er" to be the first part in the result. When the regular expression matched, the (only) subexpression was bound to the "l", so the "l" is inserted in the group together with "Er". The next match is of the "n", making "a" the next part to be returned. As the subexpression is bound to substring "n" in this case, the "n" is inserted into this group. The last group consists of the remaining string, as no more matches are found.

    By default, all parts of the string, including the empty strings, are returned -from the function, for example:

    re:split("Erlang","[lg]",[{return,list}]).

    gives

    ["Er","an",[]]

    as the matching of the "g" in the end of the string leaves an empty rest, which +from the function, for example:

    re:split("Erlang","[lg]",[{return,list}]).

    gives

    ["Er","an",[]]

    as the matching of the "g" in the end of the string leaves an empty rest, which is also returned. This behavior differs from the default behavior of the split function in Perl, where empty strings at the end are by default removed. To get -the "trimming" default behavior of Perl, specify trim as an option:

    re:split("Erlang","[lg]",[{return,list},trim]).

    gives

    ["Er","an"]

    The "trim" option says; "give me as many parts as possible except the empty +the "trimming" default behavior of Perl, specify trim as an option:

    re:split("Erlang","[lg]",[{return,list},trim]).

    gives

    ["Er","an"]

    The "trim" option says; "give me as many parts as possible except the empty ones", which sometimes can be useful. You can also specify how many parts you -want, by specifying {parts,N}:

    re:split("Erlang","[lg]",[{return,list},{parts,2}]).

    gives

    ["Er","ang"]

    Notice that the last part is "ang", not "an", as splitting was specified into +want, by specifying {parts,N}:

    re:split("Erlang","[lg]",[{return,list},{parts,2}]).

    gives

    ["Er","ang"]

    Notice that the last part is "ang", not "an", as splitting was specified into two parts, and the splitting stops when enough parts are given, which is why the -result differs from that of trim.

    More than three parts are not possible with this indata, so

    re:split("Erlang","[lg]",[{return,list},{parts,4}]).

    gives the same result as the default, which is to be viewed as "an infinite +result differs from that of trim.

    More than three parts are not possible with this indata, so

    re:split("Erlang","[lg]",[{return,list},{parts,4}]).

    gives the same result as the default, which is to be viewed as "an infinite number of parts".

    Specifying 0 as the number of parts gives the same effect as option trim. If subexpressions are captured, empty subexpressions matched at the end are also stripped from the result if trim or {parts,0} is specified.

    The trim behavior corresponds exactly to the Perl default. {parts,N}, where /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/sets.xhtml differs (HTML document, ASCII text, with very long lines (1638)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/sets.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/sets.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -43,11 +43,11 @@ respect to the aforementioned functions, their overall behavior may differ. As mentioned, this module considers elements as different if and only if they do not match (=:=), while both ordsets and gb_sets consider elements -as different if and only if they do not compare equal (==).

    Examples

    1> sets:is_element(1.0, sets:from_list([1])).
    +as different if and only if they do not compare equal (==).

    Examples

    1> sets:is_element(1.0, sets:from_list([1])).
     false
    -2> ordsets:is_element(1.0, ordsets:from_list([1])).
    +2> ordsets:is_element(1.0, ordsets:from_list([1])).
     true
    -3> gb_sets:is_element(1.0, gb_sets:from_list([1])).
    +3> gb_sets:is_element(1.0, gb_sets:from_list([1])).
     true

    See Also

    gb_sets, ordsets

    @@ -416,16 +416,16 @@ -

    Returns a new set formed from Set1 with Element inserted.

    Examples

    1> S0 = sets:new().
    -2> S1 = sets:add_element(7, S0).
    -3> sets:to_list(S1).
    -[7]
    -4> S2 = sets:add_element(42, S1).
    -5> lists:sort(sets:to_list(S2)).
    -[7,42]
    -6> S2 = sets:add_element(42, S1).
    -7> lists:sort(sets:to_list(S2)).
    -[7,42]
    +

    Returns a new set formed from Set1 with Element inserted.

    Examples

    1> S0 = sets:new().
    +2> S1 = sets:add_element(7, S0).
    +3> sets:to_list(S1).
    +[7]
    +4> S2 = sets:add_element(42, S1).
    +5> lists:sort(sets:to_list(S2)).
    +[7,42]
    +6> S2 = sets:add_element(42, S1).
    +7> lists:sort(sets:to_list(S2)).
    +[7,42]
    @@ -453,12 +453,12 @@ -

    Returns a copy of Set1 with Element removed.

    Examples

    1> S = sets:from_list([a,b]).
    -2> sets:to_list(sets:del_element(b, S)).
    -[a]
    -3> S = sets:del_element(x, S).
    -4> lists:sort(sets:to_list(S)).
    -[a,b]
    +

    Returns a copy of Set1 with Element removed.

    Examples

    1> S = sets:from_list([a,b]).
    +2> sets:to_list(sets:del_element(b, S)).
    +[a]
    +3> S = sets:del_element(x, S).
    +4> lists:sort(sets:to_list(S)).
    +[a,b]
    @@ -487,11 +487,11 @@ -

    Filters elements in Set1 using predicate function Pred.

    Examples

    1> S = sets:from_list([1,2,3,4,5,6,7]).
    -2> IsEven = fun(N) -> N rem 2 =:= 0 end.
    -3> Filtered = sets:filter(IsEven, S).
    -4> lists:sort(sets:to_list(Filtered)).
    -[2,4,6]
    +

    Filters elements in Set1 using predicate function Pred.

    Examples

    1> S = sets:from_list([1,2,3,4,5,6,7]).
    +2> IsEven = fun(N) -> N rem 2 =:= 0 end.
    +3> Filtered = sets:filter(IsEven, S).
    +4> lists:sort(sets:to_list(Filtered)).
    +[2,4,6]
    @@ -528,17 +528,17 @@

    Calls Fun(Elem) for each Elem of Set1 to update or remove elements from Set1.

    Fun/1 must return either a Boolean or a tuple {true, Value}. The function returns the set of elements for which Fun returns a new -value, with true being equivalent to {true, Elem}.

    sets:filtermap/2 behaves as if it were defined as follows:

    filtermap(Fun, Set1) ->
    -    sets:from_list(lists:filtermap(Fun, Set1)).

    Examples

    1> S = sets:from_list([2,4,5,6,8,9])
    -2> F = fun(X) ->
    +value, with true being equivalent to {true, Elem}.

    sets:filtermap/2 behaves as if it were defined as follows:

    filtermap(Fun, Set1) ->
    +    sets:from_list(lists:filtermap(Fun, Set1)).

    Examples

    1> S = sets:from_list([2,4,5,6,8,9])
    +2> F = fun(X) ->
                case X rem 2 of
    -               0 -> {true, X div 2};
    +               0 -> {true, X div 2};
                    1 -> false
                end
             end.
    -3> Set = sets:filtermap(F, S).
    -4> lists:sort(sets:to_list(Set)).
    -[1,2,3,4]
    +3>
    Set = sets:filtermap(F, S). +4> lists:sort(sets:to_list(Set)). +[1,2,3,4]
    @@ -574,9 +574,9 @@

    Folds Function over every element in Set and returns the final value of -the accumulator.

    The evaluation order is undefined.

    Examples

    1> S = sets:from_list([1,2,3,4]).
    +the accumulator.

    The evaluation order is undefined.

    Examples

    1> S = sets:from_list([1,2,3,4]).
     2> Plus = fun erlang:'+'/2.
    -3> sets:fold(Plus, 0, S).
    +3> sets:fold(Plus, 0, S).
     10
    @@ -605,9 +605,9 @@ -

    Returns a set of the elements in List.

    Examples

    1> S = sets:from_list([a,b,c]).
    -2> lists:sort(sets:to_list(S)).
    -[a,b,c]
    +

    Returns a set of the elements in List.

    Examples

    1> S = sets:from_list([a,b,c]).
    +2> lists:sort(sets:to_list(S)).
    +[a,b,c]
    @@ -637,9 +637,9 @@ -

    Returns a set of the elements in List of the given version.

    Examples

    1> S = sets:from_list([a,b,c], [{version, 1}]).
    -2> lists:sort(sets:to_list(S)).
    -[a,b,c]
    +

    Returns a set of the elements in List of the given version.

    Examples

    1> S = sets:from_list([a,b,c], [{version, 1}]).
    +2> lists:sort(sets:to_list(S)).
    +[a,b,c]
    @@ -668,15 +668,15 @@

    Returns the intersection of the non-empty list of sets.

    The intersection of multiple sets is a new set that contains only the -elements that are present in all sets.

    Examples

    1> S0 = sets:from_list([a,b,c,d]).
    -2> S1 = sets:from_list([d,e,f]).
    -3> S2 = sets:from_list([q,r])
    -4> Sets = [S0, S1, S2].
    -5> sets:to_list(sets:intersection([S0, S1, S2])).
    -[]
    -6> sets:to_list(sets:intersection([S0, S1])).
    -[d]
    -7> sets:intersection([]).
    +elements that are present in all sets.

    Examples

    1> S0 = sets:from_list([a,b,c,d]).
    +2> S1 = sets:from_list([d,e,f]).
    +3> S2 = sets:from_list([q,r])
    +4> Sets = [S0, S1, S2].
    +5> sets:to_list(sets:intersection([S0, S1, S2])).
    +[]
    +6> sets:to_list(sets:intersection([S0, S1])).
    +[d]
    +7> sets:intersection([]).
     ** exception error: no function clause matching sets:intersection([])
    @@ -707,14 +707,14 @@

    Returns the intersection of Set1 and Set2.

    The intersection of two sets is a new set that contains only the -elements that are present in both sets.

    Examples

    1> S0 = sets:from_list([a,b,c,d]).
    -2> S1 = sets:from_list([c,d,e,f]).
    -3> S2 = sets:from_list([q,r]).
    -4> Intersection = sets:intersection(S0, S1).
    -5> lists:sort(sets:to_list(Intersection)).
    -[c,d]
    -6> sets:to_list(sets:intersection(S1, S2)).
    -[]
    +elements that are present in both sets.

    Examples

    1> S0 = sets:from_list([a,b,c,d]).
    +2> S1 = sets:from_list([c,d,e,f]).
    +3> S2 = sets:from_list([q,r]).
    +4> Intersection = sets:intersection(S0, S1).
    +5> lists:sort(sets:to_list(Intersection)).
    +[c,d]
    +6> sets:to_list(sets:intersection(S1, S2)).
    +[]
    @@ -744,12 +744,12 @@

    Returns true if Set1 and Set2 are disjoint; otherwise, returns false.

    Two sets are disjoint if they have no elements in common.

    This function is equivalent to sets:intersection(Set1, Set2) =:= [], -but faster.

    Examples

    1> S0 = sets:from_list([a,b,c,d]).
    -2> S1 = sets:from_list([d,e,f]).
    -3> S2 = sets:from_list([q,r])
    -4> sets:is_disjoint(S0, S1).
    +but faster.

    Examples

    1> S0 = sets:from_list([a,b,c,d]).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/shell_default.xhtml differs (HTML document, ASCII text, with very long lines (420))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/shell_default.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/shell_default.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -23,10 +23,10 @@
     
           

    Customizing the Erlang environment.

    The functions in this module are called when no module name is specified in a -shell command.

    Consider the following shell dialog:

    1> lists:reverse("abc").
    +shell command.

    Consider the following shell dialog:

    1> lists:reverse("abc").
     "cba"
    -2> c(foo).
    -{ok, foo}

    In command one, module lists is called. In command two, no module name is +2> c(foo). +{ok, foo}

    In command one, module lists is called. In command two, no module name is specified. The shell searches module user_default followed by module shell_default for function c/1.

    shell_default is intended for "system wide" customizations to the shell. user_default is intended for "local" or individual user customizations.

    Hint

    To add your own commands to the shell, create a module called user_default and /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/shell.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (917)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/shell.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/shell.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -60,7 +60,7 @@ definitions. To facilitate matters, record definitions in modules shell_default and user_default (if loaded) are read each time a new job is started. For example, adding the following line to user_default makes the -definition of file_info readily available in the shell:

    -include_lib("kernel/include/file.hrl").

    The shell runs in two modes:

    • Normal (possibly restricted) mode, in which commands can be edited and +definition of file_info readily available in the shell:

      -include_lib("kernel/include/file.hrl").

      The shell runs in two modes:

      • Normal (possibly restricted) mode, in which commands can be edited and expressions evaluated
      • Job Control Mode, JCL, in which jobs can be started, killed, detached, and connected

      Only the currently connected job can 'talk' to the shell.

      Shell Commands

      The commands below are the built-in shell commands that are always available. In most system the commands listed in the c module are also available in the @@ -116,30 +116,30 @@ records to a module file, where FilePath should include both the path to the file and the name of the module with .erl suffix.

      Example: src/my_module.erl

    Example

    The following example is a long dialog with the shell. Commands starting with > are inputs to the shell. All other lines are output from the shell.

    strider 1> erl
    -Erlang (BEAM) emulator version 5.3 [hipe] [threads:0]
    +Erlang (BEAM) emulator version 5.3 [hipe] [threads:0]
     
    -Eshell V5.3  (abort with ^G)
    +Eshell V5.3  (abort with ^G)
     1> Str = "abcd".
    -"abcd"

    Command 1 sets variable Str to string "abcd".

    2> L = length(Str).
    -4

    Command 2 sets L to the length of string Str.

    3> Descriptor = {L, list_to_atom(Str)}.
    -{4,abcd}

    Command 3 builds the tuple Descriptor, evaluating the BIF +"abcd"

    Command 1 sets variable Str to string "abcd".

    2> L = length(Str).
    +4

    Command 2 sets L to the length of string Str.

    3> Descriptor = {L, list_to_atom(Str)}.
    +{4,abcd}

    Command 3 builds the tuple Descriptor, evaluating the BIF list_to_atom/1 .

    4> L.
    -4

    Command 4 prints the value of variable L.

    5> b().
    -Descriptor = {4,abcd}
    +4

    Command 4 prints the value of variable L.

    5> b().
    +Descriptor = {4,abcd}
     L = 4
     Str = "abcd"
     ok

    Command 5 evaluates the internal shell command b(), which is an abbreviation of "bindings". This prints the current shell variables and their bindings. ok -at the end is the return value of function b().

    6> f(L).
    +at the end is the return value of function b().

    6> f(L).
     ok

    Command 6 evaluates the internal shell command f(L) (abbreviation of -"forget"). The value of variable L is removed.

    7> b().
    -Descriptor = {4,abcd}
    +"forget"). The value of variable L is removed.

    7> b().
    +Descriptor = {4,abcd}
     Str = "abcd"
    -ok

    Command 7 prints the new bindings.

    8> f(L).
    -ok

    Command 8 has no effect, as L has no value.

    9> {L, _} = Descriptor.
    -{4,abcd}

    Command 9 performs a pattern matching operation on Descriptor, binding a new +ok

    Command 7 prints the new bindings.

    8> f(L).
    +ok

    Command 8 has no effect, as L has no value.

    9> {L, _} = Descriptor.
    +{4,abcd}

    Command 9 performs a pattern matching operation on Descriptor, binding a new value to L.

    10> L.
    -4

    Command 10 prints the current value of L.

    11> {P, Q, R} = Descriptor.
    +4

    Command 10 prints the current value of L.

    11> {P, Q, R} = Descriptor.
     ** exception error: no match of right hand side value {4,abcd}

    Command 11 tries to match {P, Q, R} against Descriptor, which is {4, abc}. The match fails and none of the new variables become bound. The printout starting with "** exception error:" is not the value of the expression (the @@ -148,74 +148,74 @@ other variables (L, Str, and so on) are unchanged.

    12> P.
     * 1:1: variable 'P' is unbound
     13> Descriptor.
    -{4,abcd}

    Commands 12 and 13 show that P is unbound because the previous command failed, -and that Descriptor has not changed.

    14>{P, Q} = Descriptor.
    -{4,abcd}
    +{4,abcd}

    Commands 12 and 13 show that P is unbound because the previous command failed, +and that Descriptor has not changed.

    14>{P, Q} = Descriptor.
    +{4,abcd}
     15> P.
    -4

    Commands 14 and 15 show a correct match where P and Q are bound.

    16> f().
    -ok

    Command 16 clears all bindings.

    The next few commands assume that test1:demo(X) is defined as follows:

    demo(X) ->
    -    put(aa, worked),
    +4

    Commands 14 and 15 show a correct match where P and Q are bound.

    16> f().
    +ok

    Command 16 clears all bindings.

    The next few commands assume that test1:demo(X) is defined as follows:

    demo(X) ->
    +    put(aa, worked),
         X = 1,
    -    X + 10.
    17> put(aa, hello).
    +    X + 10.
    17> put(aa, hello).
     undefined
    -18> get(aa).
    +18> get(aa).
     hello

    Commands 17 and 18 set and inspect the value of item aa in the process -dictionary.

    19> Y = test1:demo(1).
    +dictionary.

    19> Y = test1:demo(1).
     11

    Command 19 evaluates test1:demo(1). The evaluation succeeds and the changes made in the process dictionary become visible to the shell. The new value of -dictionary item aa can be seen in command 20.

    20> get().
    -[{aa,worked}]
    -21> put(aa, hello).
    +dictionary item aa can be seen in command 20.

    20> get().
    +[{aa,worked}]
    +21> put(aa, hello).
     worked
    -22> Z = test1:demo(2).
    +22> Z = test1:demo(2).
     ** exception error: no match of right hand side value 1
          in function  test1:demo/1

    Commands 21 and 22 change the value of dictionary item aa to hello and call test1:demo(2). Evaluation fails and the changes made to the dictionary in test1:demo(2), before the error occurred, are discarded.

    23> Z.
     * 1:1: variable 'Z' is unbound
    -24> get(aa).
    +24> get(aa).
     hello

    Commands 23 and 24 show that Z was not bound and that dictionary item aa has -retained its original value.

    25> erase(), put(aa, hello).
    +retained its original value.

    25> erase(), put(aa, hello).
     undefined
    -26> spawn(test1, demo, [1]).
    +26> spawn(test1, demo, [1]).
     <0.57.0>
    -27> get(aa).
    +27> get(aa).
     hello

    Commands 25, 26, and 27 show the effect of evaluating test1:demo(1) in the background. In this case, the expression is evaluated in a newly spawned process. Any changes made in the process dictionary are local to the newly -spawned process and therefore not visible to the shell.

    28> io:format("hello hello\n").
    +spawned process and therefore not visible to the shell.

    28> io:format("hello hello\n").
     hello hello
     ok
    -29> e(28).
    +29> e(28).
     hello hello
     ok
    -30> v(28).
    +30> v(28).
     ok

    Commands 28, 29 and 30 use the history facilities of the shell. Command 29 re-evaluates command 28. Command 30 uses the value (result) of command 28. In the cases of a pure function (a function with no side effects), the result is the same. For a function with side effects, the result can be different.

    The next few commands show some record manipulation. It is assumed that ex.erl -defines a record as follows:

    -record(rec, {a, b = val()}).

    val() ->
        3.

    31> c(ex).
    -{ok,ex}
    -32> rr(ex).
    -[rec]

    Commands 31 and 32 compile file ex.erl and read the record definitions in +defines a record as follows:

    -record(rec, {a, b = val()}).

    val() ->
        3.

    31> c(ex).
    +{ok,ex}
    +32> rr(ex).
    +[rec]

    Commands 31 and 32 compile file ex.erl and read the record definitions in ex.beam. If the compiler did not output any record definitions on the BEAM -file, rr(ex) tries to read record definitions from the source file instead.

    33> rl(rec).
    --record(rec,{a,b = val()}).
    -ok

    Command 33 prints the definition of the record named rec.

    34> #rec{}.
    +file, rr(ex) tries to read record definitions from the source file instead.

    33> rl(rec).
    +-record(rec,{a,b = val()}).
    +ok

    Command 33 prints the definition of the record named rec.

    34> #rec{}.
     ** exception error: undefined shell command val/0

    Command 34 tries to create a rec record, but fails as function val/0 is -undefined.

    35> #rec{b = 3}.
    -#rec{a = undefined,b = 3}

    Command 35 shows the workaround: explicitly assign values to record fields that -cannot otherwise be initialized.

    36> rp(v(-1)).
    -#rec{a = undefined,b = 3}
    +undefined.

    35> #rec{b = 3}.
    +#rec{a = undefined,b = 3}

    Command 35 shows the workaround: explicitly assign values to record fields that +cannot otherwise be initialized.

    36> rp(v(-1)).
    +#rec{a = undefined,b = 3}
     ok

    Command 36 prints the newly created record using record definitions maintained -by the shell.

    37> rd(rec, {f = orddict:new()}).
    +by the shell.

    37> rd(rec, {f = orddict:new()}).
     rec

    Command 37 defines a record directly in the shell. The definition replaces the -one read from file ex.beam.

    38> #rec{}.
    -#rec{f = []}
    -ok

    Command 38 creates a record using the new definition, and prints the result.

    39> rd(rec, {c}), A.
    +one read from file ex.beam.

    38> #rec{}.
    +#rec{f = []}
    +ok

    Command 38 creates a record using the new definition, and prints the result.

    39> rd(rec, {c}), A.
     * 1:15: variable 'A' is unbound
    -40> #rec{}.
    -#rec{c = undefined}
    +40> #rec{}.
    +#rec{c = undefined}
     ok

    Command 39 and 40 show that record definitions are updated as side effects. The evaluation of the command fails, but the definition of rec has been carried out.

    For the next command, it is assumed that test1:loop(N) is defined as follows:

    loop(N) ->
        io:format("Hello Number: ~w~n", [N]),
        loop(N+1).

    41> test1:loop(0).
    @@ -241,31 +241,31 @@
     JCL mode the user can start and stop jobs.

    In this particular case, command i ("interrupt") terminates the looping program, and command c connects to the shell again. As the process was running in the background before we killed it, more printouts occur before message -"** exception exit: killed" is shown.

    42> E = ets:new(t, []).
    -#Ref<0.1662103692.2407923716.214192>

    Command 42 creates an ETS table.

    43> ets:insert({d,1,2}).
    +"** exception exit: killed" is shown.

    42> E = ets:new(t, []).
    +#Ref<0.1662103692.2407923716.214192>

    Command 42 creates an ETS table.

    43> ets:insert({d,1,2}).
     ** exception error: undefined function ets:insert/1

    Command 43 tries to insert a tuple into the ETS table, but the first argument -(the table) is missing. The exception kills the evaluator process.

    44> ets:insert(E, {d,1,2}).
    +(the table) is missing. The exception kills the evaluator process.

    44> ets:insert(E, {d,1,2}).
     ** exception error: argument is of wrong type
          in function  ets:insert/2
             called as ets:insert(16,{d,1,2})

    Command 44 corrects the mistake, but the ETS table has been destroyed as it was -owned by the killed evaluator process.

    45> f(E).
    +owned by the killed evaluator process.

    45> f(E).
     ok
    -46> catch_exception(true).
    +46> catch_exception(true).
     false

    Command 46 sets the exception handling of the evaluator process to true. The exception handling can also be set when starting Erlang by -erl -stdlib shell_catch_exception true.

    47> E = ets:new(t, []).
    +erl -stdlib shell_catch_exception true.

    47> E = ets:new(t, []).
     #Ref<0.1662103692.2407923716.214197>
    -48> ets:insert({d,1,2}).
    +48> ets:insert({d,1,2}).
     * exception error: undefined function ets:insert/1

    Command 48 makes the same mistake as in command 43, but this time the evaluator process lives on. The single star at the beginning of the printout signals that -the exception has been caught.

    49> ets:insert(E, {d,1,2}).
    -true

    Command 49 successfully inserts the tuple into the ETS table.

    50> ets:insert(#Ref<0.1662103692.2407923716.214197>, {e,3,4}).
    +the exception has been caught.

    49> ets:insert(E, {d,1,2}).
    +true

    Command 49 successfully inserts the tuple into the ETS table.

    50> ets:insert(#Ref<0.1662103692.2407923716.214197>, {e,3,4}).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/slave.xhtml differs (HTML document, ASCII text, with very long lines (979))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/slave.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/slave.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -258,7 +258,7 @@
     at a master node. A pseudo server is an intermediary that only has the same
     registered name as the real server.

    For example, if you have started a slave node N and want to execute pxw graphics code on this node, you can start server pxw_server as a pseudo server -at the slave node. This is illustrated as follows:

    rpc:call(N, slave, pseudo, [node(), [pxw_server]]).
    +at the slave node. This is illustrated as follows:

    rpc:call(N, slave, pseudo, [node(), [pxw_server]]).
    @@ -412,9 +412,9 @@ passed to the new node and can be used for a variety of purposes; see erl(1).

    As an example, suppose that you want to start a slave node at host H with node name Name@H and want the slave node to have the following properties:

    • Directory Dir is to be added to the code path.
    • The Mnesia directory is to be set to M.
    • The Unix DISPLAY environment variable is to be set to the display of the -master node.

    The following code is executed to achieve this:

    E = " -env DISPLAY " ++ net_adm:localhost() ++ ":0 ",
    +master node.

    The following code is executed to achieve this:

    E = " -env DISPLAY " ++ net_adm:localhost() ++ ":0 ",
     Arg = "-mnesia_dir " ++ M ++ " -pa " ++ Dir ++ E,
    -slave:start(H, Name, Arg).

    The function returns {ok, Node}, where Node is the name of the new node, +slave:start(H, Name, Arg).

    The function returns {ok, Node}, where Node is the name of the new node, otherwise {error, Reason}, where Reason can be one of:

    • timeout - The master node failed to get in contact with the slave node. This can occur in a number of circumstances:

      • Erlang/OTP is not installed on the remote host.
      • The file system on the other host has a different structure to the the master.
      • The Erlang nodes have different cookies.
    • no_rsh - No remote shell program was found on the computer. Note that /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/sofs.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1348)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/sofs.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/sofs.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -156,16 +156,16 @@ selecting, duplicating, or rearranging parts of the elements.

    • Specifying a SetFun as an integer I is equivalent to specifying {external, fun(X) -> element(I, X) end}, but is to be preferred, as it makes it possible to handle this case even more efficiently.

    Examples of valid SetFuns:

    fun sofs:union/1
    -fun(S) -> sofs:partition(1, S) end
    -fun(S) -> sofs:from_term(sofs:no_elements(S)) end
    -{external, fun(A) -> A end}
    -{external, fun({A,_,C}) -> {C,A} end}
    -{external, fun({_,{_,C}}) -> C end}
    -{external, fun({_,{_,{_,E}=C}}) -> {E,{E,C}} end}
    +fun(S) -> sofs:partition(1, S) end
    +fun(S) -> sofs:from_term(sofs:no_elements(S)) end
    +{external, fun(A) -> A end}
    +{external, fun({A,_,C}) -> {C,A} end}
    +{external, fun({_,{_,C}}) -> C end}
    +{external, fun({_,{_,{_,E}=C}}) -> {E,{E,C}} end}
     2

    Examples of invalid SetFuns:

    fun sofs:no_elements/1
    -{external, fun(A) -> 2 * A end}
    -{external, fun({A,B,C}) -> A + B + C end}
    -{external, fun lists:sum/1}

    The order in which a SetFun is applied to the elements of an unordered set is +{external, fun(A) -> 2 * A end} +{external, fun({A,B,C}) -> A + B + C end} +{external, fun lists:sum/1}

    The order in which a SetFun is applied to the elements of an unordered set is not specified, and can change in future versions of this module.

    The execution time of the functions of this module is dominated by the time it takes to sort lists. When no sorting is needed, the execution time is in the worst case proportional to the sum of the sizes of the input arguments and the @@ -1655,9 +1655,9 @@

    Creates a function.

    a_function(F, T) is equivalent to -from_term(F, T) if the result is a function.

    Examples

    1> sofs:is_a_function(sofs:a_function([{1,a},{2,b},{3,c}])).
    +from_term(F, T) if the result is a function.

    Examples

    1> sofs:is_a_function(sofs:a_function([{1,a},{2,b},{3,c}])).
     true
    -2> sofs:a_function([{1,a},{1,b}]).
    +2> sofs:a_function([{1,a},{1,b}]).
     ** exception error: bad_function
          in function  sofs:a_function/1
    @@ -1692,10 +1692,10 @@ belongs to SetOfSets and E belongs to Set.

    If SetOfSets is a partition of a set X and R is the equivalence relation in X induced by SetOfSets, then the returned relation is the canonical map from X onto the equivalence classes with -respect to R.

    Examples

    1> Ss = sofs:from_term([[a,b],[b,c]]).
    -2> CR = sofs:canonical_relation(Ss).
    -3> sofs:to_external(CR).
    -[{a,[a,b]},{b,[a,b]},{b,[b,c]},{c,[b,c]}]
    +respect to R.

    Examples

    1> Ss = sofs:from_term([[a,b],[b,c]]).
    +2> CR = sofs:canonical_relation(Ss).
    +3> sofs:to_external(CR).
    +[{a,[a,b]},{b,[a,b]},{b,[b,c]},{c,[b,c]}]
    @@ -1725,12 +1725,12 @@

    Returns the composite of the functions Function1 and -Function2.

    Examples

    1> F1 = sofs:a_function([{a,1},{b,2},{c,2}]).
    -2> F2 = sofs:a_function([{1,x},{2,y},{3,z}]).
    -3> F = sofs:composite(F1, F2).
    -4> sofs:to_external(F).
    -[{a,x},{b,y},{c,y}]
    -5> sofs:composite(F2, F1).
    +Function2.

    Examples

    1> F1 = sofs:a_function([{a,1},{b,2},{c,2}]).
    +2> F2 = sofs:a_function([{1,x},{2,y},{3,z}]).
    +3> F = sofs:composite(F1, F2).
    +4> sofs:to_external(F).
    +[{a,x},{b,y},{c,y}]
    +5> sofs:composite(F2, F1).
     ** exception error: bad_function
          in function  sofs:composite/2
    @@ -1762,11 +1762,11 @@

    Creates the function that maps each element of set Set -onto AnySet.

    Examples

    1> S = sofs:set([a,b]).
    -2> E = sofs:from_term(1).
    -3> R = sofs:constant_function(S, E).
    -4> sofs:to_external(R).
    -[{a,1},{b,1}]
    +onto AnySet.

    Examples

    1> S = sofs:set([a,b]).
    +2> E = sofs:from_term(1).
    +3> R = sofs:constant_function(S, E).
    +4> sofs:to_external(R).
    +[{a,1},{b,1}]
    @@ -1795,10 +1795,10 @@

    Returns the converse of the binary relation BinRel1.

    See inverse/1 for a similar function that applies only to invertible -functions.

    Examples

    1> R1 = sofs:relation([{1,a},{2,b},{3,a}]).
    -2> R2 = sofs:converse(R1).
    -3> sofs:to_external(R2).
    -[{a,1},{a,3},{b,2}]
    +functions.

    Examples

    1> R1 = sofs:relation([{1,a},{2,b},{3,a}]).
    +2> R2 = sofs:converse(R1).
    +3> sofs:to_external(R2).
    +[{a,1},{a,3},{b,2}]
    @@ -1826,12 +1826,12 @@ -

    Returns the difference of the sets Set1 and Set2.

    Examples

    1> S0 = sofs:set([a,b,c,d]).
    -2> S1 = sofs:set([c,d,e,f]).
    -3> sofs:to_external(sofs:difference(S0, S1)).
    -[a,b]
    -4> sofs:to_external(sofs:difference(S1, S0)).
    -[e,f]
    +

    Returns the difference of the sets Set1 and Set2.

    Examples

    1> S0 = sofs:set([a,b,c,d]).
    +2> S1 = sofs:set([c,d,e,f]).
    +3> sofs:to_external(sofs:difference(S0, S1)).
    +[a,b]
    +4> sofs:to_external(sofs:difference(S1, S0)).
    +[e,f]
    @@ -1893,15 +1893,15 @@ a. It is assumed that Type is a valid type of the external set of the family.

    If G is a directed graph, it holds that the vertices and edges of G are the same as the vertices and edges of -family_to_digraph(digraph_to_family(G)).

    Examples

    1> G = digraph:new().
    -2> digraph:add_vertex(G, 1).
    -3> digraph:add_vertex(G, a).
    -4> digraph:add_vertex(G, b).
    -5> digraph:add_edge(G, 1, a).
    -6> digraph:add_edge(G, 1, b).
    -7> F = sofs:digraph_to_family(G).
    -8> sofs:to_external(F).
    -[{1,[a,b]},{a,[]},{b,[]}]
    +family_to_digraph(digraph_to_family(G)).

    Examples

    1> G = digraph:new().
    +2> digraph:add_vertex(G, 1).
    +3> digraph:add_vertex(G, a).
    +4> digraph:add_vertex(G, b).
    +5> digraph:add_edge(G, 1, a).
    +6> digraph:add_edge(G, 1, b).
    +7> F = sofs:digraph_to_family(G).
    +8> sofs:to_external(F).
    +[{1,[a,b]},{a,[]},{b,[]}]
    @@ -1929,10 +1929,10 @@ -

    Returns the domain of the binary relation BinRel.

    Examples

    1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]).
    -2> S = sofs:domain(R).
    -3> sofs:to_external(S).
    -[1,2]
    +

    Returns the domain of the binary relation BinRel.

    Examples

    1> R = sofs:relation([{1,a},{1,b},{2,b},{2,c}]).
    +2> S = sofs:domain(R).
    +3> sofs:to_external(S).
    +[1,2]
    @@ -1962,11 +1962,11 @@

    Returns the difference between the binary relation BinRel1 and the -restriction of BinRel1 to Set.

    Examples

    1> R1 = sofs:relation([{1,a},{2,b},{3,c}]).
    -2> S = sofs:set([2,4,6]).
    -3> R2 = sofs:drestriction(R1, S).
    -4> sofs:to_external(R2).
    -[{1,a},{3,c}]

    drestriction(R, S) is equivalent to +restriction of BinRel1 to Set.

    Examples

    1> R1 = sofs:relation([{1,a},{2,b},{3,c}]).
    +2> S = sofs:set([2,4,6]).
    +3> R2 = sofs:drestriction(R1, S).
    +4> sofs:to_external(R2).
    +[{1,a},{3,c}]

    drestriction(R, S) is equivalent to difference(R, restriction(R, S)).

    @@ -1997,12 +1997,12 @@

    Returns a subset of Set1 containing those elements that do not give an element -in Set2 as the result of applying SetFun.

    Examples

    1> SetFun = {external, fun({_A,B,C}) -> {B,C} end}.
    -2> R1 = sofs:relation([{a,aa,1},{b,bb,2},{c,cc,3}]).
    -3> R2 = sofs:relation([{bb,2},{cc,3},{dd,4}]).
    -4> R3 = sofs:drestriction(SetFun, R1, R2).
    -5> sofs:to_external(R3).
    -[{a,aa,1}]

    drestriction(F, S1, S2) is equivalent to +in Set2 as the result of applying SetFun.

    Examples

    1> SetFun = {external, fun({_A,B,C}) -> {B,C} end}.
    +2> R1 = sofs:relation([{a,aa,1},{b,bb,2},{c,cc,3}]).
    +3> R2 = sofs:relation([{bb,2},{cc,3},{dd,4}]).
    +4> R3 = sofs:drestriction(SetFun, R1, R2).
    +5> sofs:to_external(R3).
    +[{a,aa,1}]

    drestriction(F, S1, S2) is equivalent to difference(S1, restriction(F, S1, S2)).

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/stdlib_app.xhtml differs (HTML document, ASCII text, with very long lines (1971)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/stdlib_app.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/stdlib_app.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -42,13 +42,13 @@ prompt function takes the main prompt as its only parameter.

  • shell_saved_results = integer() >= 0 - Can be used to determine how many results are saved by the Erlang shell.

  • shell_session_slogan = string() | fun() -> string()) - The slogan printed when starting an Erlang shell. Example:

    $ erl -stdlib shell_session_slogan '"Test slogan"'
    -Erlang/OTP 26 [DEVELOPMENT] [erts-13.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
    +Erlang/OTP 26 [DEVELOPMENT] [erts-13.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
     
     Test slogan
     1>
  • shell_slogan = string() | fun(() -> string()) - The slogan printed when starting the Erlang shell subsystem. Example:

    $ erl -stdlib shell_slogan '"Test slogan"'
     Test slogan
    -Eshell V13.0.2  (abort with ^G)
    +Eshell V13.0.2  (abort with ^G)
     1>

    The default is the return value of erlang:system_info(system_version).

  • shell_strings = boolean() - Can be used to determine how the Erlang shell outputs lists of integers.

  • shell_hints = boolean() - Can be used to enable/disable /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/string.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1067)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/string.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/string.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -43,14 +43,14 @@ expect UTF-8 binaries but not all functions verify that all binaries are encoded correctly.

    Unless otherwise specified the return value type is the same as the input type. That is, binary input returns binary output, list input returns a list output, -and mixed input can return a mixed output.

    1> string:trim("  sarah  ").
    +and mixed input can return a mixed output.

    1> string:trim("  sarah  ").
     "sarah"
    -2> string:trim(<<"  sarah  ">>).
    -<<"sarah">>
    -3> string:lexemes("foo bar", " ").
    -["foo","bar"]
    -4> string:lexemes(<<"foo bar">>, " ").
    -[<<"foo">>,<<"bar">>]

    This module has been reworked in Erlang/OTP 20 to handle unicode:chardata/0 +2> string:trim(<<" sarah ">>). +<<"sarah">> +3> string:lexemes("foo bar", " "). +["foo","bar"] +4> string:lexemes(<<"foo bar">>, " "). +[<<"foo">>,<<"bar">>]

    This module has been reworked in Erlang/OTP 20 to handle unicode:chardata/0 and operate on grapheme clusters. The old functions that only work on Latin-1 lists as input are still available but should not be used, they will be @@ -944,7 +944,7 @@

    Converts String to a case-agnostic comparable string. Function casefold/1 is preferred over lowercase/1 -when two strings are to be compared for equality. See also equal/4.

    Example:

    1> string:casefold("Ω and ẞ SHARP S").
    +when two strings are to be compared for equality. See also equal/4.

    Example:

    1> string:casefold("Ω and ẞ SHARP S").
     "ω and ss sharp s"
    @@ -976,9 +976,9 @@

    Returns a string where any trailing \n or \r\n have been removed from -String.

    Example:

    182> string:chomp(<<"\nHello\n\n">>).
    -<<"\nHello">>
    -183> string:chomp("\nHello\r\r\n").
    +String.

    Example:

    182> string:chomp(<<"\nHello\n\n">>).
    +<<"\nHello">>
    +183> string:chomp("\nHello\r\r\n").
     "\nHello\r"
    @@ -1079,11 +1079,11 @@ nfc, nfd, nfkc, and -nfkd.

    Example:

    1> string:equal("åäö", <<"åäö"/utf8>>).
    +nfkd.

    Example:

    1> string:equal("åäö", <<"åäö"/utf8>>).
     true
    -2> string:equal("åäö", unicode:characters_to_nfd_binary("åäö")).
    +2> string:equal("åäö", unicode:characters_to_nfd_binary("åäö")).
     false
    -3> string:equal("åäö", unicode:characters_to_nfd_binary("ÅÄÖ"), true, nfc).
    +3> string:equal("åäö", unicode:characters_to_nfd_binary("ÅÄÖ"), true, nfc).
     true
    @@ -1149,13 +1149,13 @@

    Removes anything before SearchPattern in String and returns the remainder of the string or nomatch if SearchPattern is not found. Dir, which can be leading or trailing, indicates from which direction characters are to be -searched.

    Example:

    1> string:find("ab..cd..ef", ".").
    +searched.

    Example:

    1> string:find("ab..cd..ef", ".").
     "..cd..ef"
    -2> string:find(<<"ab..cd..ef">>, "..", trailing).
    -<<"..ef">>
    -3> string:find(<<"ab..cd..ef">>, "x", leading).
    +2> string:find(<<"ab..cd..ef">>, "..", trailing).
    +<<"..ef">>
    +3> string:find(<<"ab..cd..ef">>, "x", leading).
     nomatch
    -4> string:find("ab..cd..ef", "x", trailing).
    +4> string:find("ab..cd..ef", "x", trailing).
     nomatch
    @@ -1186,9 +1186,9 @@ -

    Returns true if String is the empty string, otherwise false.

    Example:

    1> string:is_empty("foo").
    +

    Returns true if String is the empty string, otherwise false.

    Example:

    1> string:is_empty("foo").
     false
    -2> string:is_empty(["",<<>>]).
    +2> string:is_empty(["",<<>>]).
     true
    @@ -1226,13 +1226,13 @@

    Returns a float between +0.0 and 1.0 representing the Jaro similarity between the given strings. Strings with a higher similarity will score closer -to 1.0, with +0.0 meaning no similarity and 1.0 meaning an exact match.

    Example:

    1> string:jaro_similarity("ditto", "ditto").
    +to 1.0, with +0.0 meaning no similarity and 1.0 meaning an exact match.

    Example:

    1> string:jaro_similarity("ditto", "ditto").
     1.0
    -2> string:jaro_similarity("foo", "bar").
    +2> string:jaro_similarity("foo", "bar").
     +0.0
    -3> string:jaro_similarity("michelle", "michael").
    +3> string:jaro_similarity("michelle", "michael").
     0.8690476190476191
    -4> string:jaro_similarity(<<"Édouard"/utf8>>, <<"Claude">>).
    +4> string:jaro_similarity(<<"Édouard"/utf8>>, <<"Claude">>).
     0.5317460317460317

    The Jaro distance between two strings can be calculated with JaroDistance = 1.0 - JaroSimilarity.

    @@ -1264,9 +1264,9 @@ -

    Returns the number of grapheme clusters in String.

    Example:

    1> string:length("ß↑e̊").
    +

    Returns the number of grapheme clusters in String.

    Example:

    1> string:length("ß↑e̊").
     3
    -2> string:length(<<195,159,226,134,145,101,204,138>>).
    +2> string:length(<<195,159,226,134,145,101,204,138>>).
     3
    @@ -1301,10 +1301,10 @@

    Returns a list of lexemes in String, separated by the grapheme clusters in SeparatorList.

    Notice that, as shown in this example, two or more adjacent separator graphemes clusters in String are treated as one. That is, there are no empty strings in -the resulting list of lexemes. See also split/3 which returns empty strings.

    Notice that [$\r,$\n] is one grapheme cluster.

    Example:

    1> string:lexemes("abc de̊fxxghix jkl\r\nfoo", "x e" ++ [[$\r,$\n]]).
    -["abc","de̊f","ghi","jkl","foo"]
    -2> string:lexemes(<<"abc de̊fxxghix jkl\r\nfoo"/utf8>>, "x e" ++ [$\r,$\n]).
    -[<<"abc">>,<<"de̊f"/utf8>>,<<"ghi">>,<<"jkl\r\nfoo">>]
    +the resulting list of lexemes. See also split/3 which returns empty strings.

    Notice that [$\r,$\n] is one grapheme cluster.

    Example:

    1> string:lexemes("abc de̊fxxghix jkl\r\nfoo", "x e" ++ [[$\r,$\n]]).
    +["abc","de̊f","ghi","jkl","foo"]
    +2> string:lexemes(<<"abc de̊fxxghix jkl\r\nfoo"/utf8>>, "x e" ++ [$\r,$\n]).
    +[<<"abc">>,<<"de̊f"/utf8>>,<<"ghi">>,<<"jkl\r\nfoo">>]
    @@ -1335,7 +1335,7 @@

    Converts String to lowercase.

    Notice that function casefold/1 should be used when converting a string to be -tested for equality.

    Example:

    2> string:lowercase(string:uppercase("Michał")).
    +tested for equality.

    Example:

    2> string:lowercase(string:uppercase("Michał")).
     "michał"
    @@ -1369,8 +1369,8 @@

    Returns the first codepoint in String and the rest of String in the tail. Returns an empty list if String is empty or an {error, String} tuple if the -next byte is invalid.

    Example:

    1> string:next_codepoint(unicode:characters_to_binary("e̊fg")).
    -[101|<<"̊fg"/utf8>>]
    +next byte is invalid.

    Example:

    1> string:next_codepoint(unicode:characters_to_binary("e̊fg")).
    +[101|<<"̊fg"/utf8>>]
    @@ -1404,8 +1404,8 @@

    Returns the first grapheme cluster in String and the rest of String in the tail. Returns an empty list if String is empty or an {error, String} tuple -if the next byte is invalid.

    Example:

    1> string:next_grapheme(unicode:characters_to_binary("e̊fg")).
    -["e̊"|<<"fg">>]
    +if the next byte is invalid.

    Example:

    1> string:next_grapheme(unicode:characters_to_binary("e̊fg")).
    +["e̊"|<<"fg">>]
    @@ -1440,7 +1440,7 @@

    Returns lexeme number N in String, where lexemes are separated by the -grapheme clusters in SeparatorList.

    Example:

    1> string:nth_lexeme("abc.de̊f.ghiejkl", 3, ".e").
    +grapheme clusters in SeparatorList.

    Example:

    1> string:nth_lexeme("abc.de̊f.ghiejkl", 3, ".e").
     "ghi"
    @@ -1538,11 +1538,11 @@

    Pads String to Length with grapheme cluster Char. Dir, which can be -leading, trailing, or both, indicates where the padding should be added.

    Example:

    1> string:pad(<<"He̊llö"/utf8>>, 8).
    -[<<72,101,204,138,108,108,195,182>>,32,32,32]
    -2> io:format("'~ts'~n",[string:pad("He̊llö", 8, leading)]).
    +leading, trailing, or both, indicates where the padding should be added.

    Example:

    1> string:pad(<<"He̊llö"/utf8>>, 8).
    +[<<72,101,204,138,108,108,195,182>>,32,32,32]
    +2> io:format("'~ts'~n",[string:pad("He̊llö", 8, leading)]).
     '   He̊llö'
    -3> io:format("'~ts'~n",[string:pad("He̊llö", 8, both)]).
    +3> io:format("'~ts'~n",[string:pad("He̊llö", 8, both)]).
     ' He̊llö  '
    @@ -1574,9 +1574,9 @@

    If Prefix is the prefix of String, removes it and returns the remainder of -String, otherwise returns nomatch.

    Example:

    1> string:prefix(<<"prefix of string">>, "pre").
    -<<"fix of string">>
    -2> string:prefix("pre", "prefix").
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/supervisor.xhtml differs (HTML document, ASCII text, with very long lines (896))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/supervisor.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/supervisor.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -40,11 +40,11 @@
     left to right according to this list. When the supervisor is going to terminate,
     it first terminates its child processes in reversed start order, from right to
     left.

    Supervisor flags

    The supervisor properties are defined by the supervisor flags. The type -definition for the supervisor flags is as follows:

    sup_flags() = #{strategy => strategy(),           % optional
    -                intensity => non_neg_integer(),   % optional
    -                period => pos_integer(),          % optional
    -                hibernate_after => timeout(),     % optional, available since OTP 28.0
    -                auto_shutdown => auto_shutdown()} % optional

    Restart Strategies

    A supervisor can have one of the following restart strategies specified with +definition for the supervisor flags is as follows:

    sup_flags() = #{strategy => strategy(),           % optional
    +                intensity => non_neg_integer(),   % optional
    +                period => pos_integer(),          % optional
    +                hibernate_after => timeout(),     % optional, available since OTP 28.0
    +                auto_shutdown => auto_shutdown()} % optional

    Restart Strategies

    A supervisor can have one of the following restart strategies specified with the strategy key in the above map:

    • one_for_one - If one child process terminates and is to be restarted, only that child process is affected. This is the default restart strategy.

    • one_for_all - If one child process terminates and is to be restarted, all other child processes are terminated and then all child processes are @@ -90,13 +90,13 @@ this feature will also compile and run with older OTP versions.

      However, such applications, when compiled with an OTP version that predates the appearance of the automatic shutdown feature, will leak processes because the automatic shutdowns they rely on will not happen.

      It is up to implementors to take proper precautions if they expect that their -applications may be compiled with older OTP versions.

      Child specification

      The type definition of a child specification is as follows:

      child_spec() = #{id => child_id(),             % mandatory
      -                 start => mfargs(),            % mandatory
      -                 restart => restart(),         % optional
      -                 significant => significant(), % optional
      -                 shutdown => shutdown(),       % optional
      -                 type => worker(),             % optional
      -                 modules => modules()}         % optional

      The old tuple format is kept for backwards compatibility, see child_spec/0, +applications may be compiled with older OTP versions.

      Child specification

      The type definition of a child specification is as follows:

      child_spec() = #{id => child_id(),             % mandatory
      +                 start => mfargs(),            % mandatory
      +                 restart => restart(),         % optional
      +                 significant => significant(), % optional
      +                 shutdown => shutdown(),       % optional
      +                 type => worker(),             % optional
      +                 modules => modules()}         % optional

      The old tuple format is kept for backwards compatibility, see child_spec/0, but the map is preferred.

      • id is used to identify the child specification internally by the supervisor.

        The id key is mandatory.

        Notice that this identifier on occasion has been called "name". As far as possible, the terms "identifier" or "id" are now used but to keep backward compatibility, some occurences of "name" can still be found, for example in /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/terminal_interface.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (681)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/terminal_interface.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/terminal_interface.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -33,18 +33,18 @@ ║ │ │ ║ ║ │ │ ║ ╚═══════╧═══════╧═══════╝

    We will use the alternate screen buffer for our game so first we need to set that up:

    #!/usr/bin/env escript
    -main(_Args) ->
    +main(_Args) ->
         
    -    io:put_chars("\e[?1049h"), %% Enable alternate screen buffer
    -    io:put_chars("\e[?25l"), %% Hide the cursor
    -    draw_board(),
    -    timer:sleep(5000),
    -    io:put_chars("\e[?25h"), %% Show the cursor
    -    io:put_chars("\e[?1049l"), %% Disable alternate screen buffer
    -    ok.

    We then use the box drawing parts of Unicode to draw our board:

    draw_board() ->
    -    io:put_chars("\e[5;0H"), %% Move cursor to top left
    -    io:put_chars(
    -      ["     ╔═══════╤═══════╤═══════╗\r\n",
    +    io:put_chars("\e[?1049h"), %% Enable alternate screen buffer
    +    io:put_chars("\e[?25l"), %% Hide the cursor
    +    draw_board(),
    +    timer:sleep(5000),
    +    io:put_chars("\e[?25h"), %% Show the cursor
    +    io:put_chars("\e[?1049l"), %% Disable alternate screen buffer
    +    ok.

    We then use the box drawing parts of Unicode to draw our board:

    draw_board() ->
    +    io:put_chars("\e[5;0H"), %% Move cursor to top left
    +    io:put_chars(
    +      ["     ╔═══════╤═══════╤═══════╗\r\n",
            "     ║       │       │       ║\r\n",
            "     ║       │       │       ║     Place an X by pressing Enter\r\n",
            "     ║       │       │       ║\r\n",
    @@ -56,51 +56,51 @@
            "     ║       │       │       ║\r\n",
            "     ║       │       │       ║\r\n",
            "     ║       │       │       ║\r\n",
    -       "     ╚═══════╧═══════╧═══════╝\r\n"]),
    +       "     ╚═══════╧═══════╧═══════╝\r\n"]),
         ok.

    Let us add some interactivity to our game! To do that we need to change the shell from running in cooked to raw mode. This is done by calling shell:start_interactive({noshell, raw}). We can then use io:get_chars/2 to read key strokes from the user. The key strokes will be returned as ANSI escape codes, -so we will have need to handle the codes for up, down, left, right and enter.

    It could look something like this:

    main(_Args) ->
    -    ok = shell:start_interactive({noshell, raw}),
    +so we will have need to handle the codes for up, down, left, right and enter.

    It could look something like this:

    main(_Args) ->
    +    ok = shell:start_interactive({noshell, raw}),
         
    -    io:put_chars("\e[?1049h"), %% Enable alternate screen buffer
    -    io:put_chars("\e[?25l"), %% Hide the cursor
    -    draw_board(),
    -    loop(0),
    -    io:put_chars("\e[?25h"), %% Show the cursor
    -    io:put_chars("\e[?1049l"), %% Disable alternate screen buffer
    +    io:put_chars("\e[?1049h"), %% Enable alternate screen buffer
    +    io:put_chars("\e[?25l"), %% Hide the cursor
    +    draw_board(),
    +    loop(0),
    +    io:put_chars("\e[?25h"), %% Show the cursor
    +    io:put_chars("\e[?1049l"), %% Disable alternate screen buffer
         ok.
     
    -loop(Pos) ->
    -    io:put_chars(draw_selection(Pos)),
    +loop(Pos) ->
    +    io:put_chars(draw_selection(Pos)),
         %% Read at most 1024 characters from stdin.
    -    Chars = io:get_chars("", 1024),
    -    case handle_input(Chars, Pos) of
    +    Chars = io:get_chars("", 1024),
    +    case handle_input(Chars, Pos) of
             stop -> stop;
             NewPos ->
    -            io:put_chars(clear_selection(Pos)),
    -            loop(NewPos)
    +            io:put_chars(clear_selection(Pos)),
    +            loop(NewPos)
         end.
     
    -handle_input("\e[A" ++ Rest, Pos) ->
    +handle_input("\e[A" ++ Rest, Pos) ->
         %% Up key
    -    handle_input(Rest, max(0, Pos - 3));
    -handle_input("\e[B" ++ Rest, Pos) ->
    +    handle_input(Rest, max(0, Pos - 3));
    +handle_input("\e[B" ++ Rest, Pos) ->
         %% Down key
    -    handle_input(Rest, min(8, Pos + 3));
    -handle_input("\e[C" ++ Rest, Pos) ->
    +    handle_input(Rest, min(8, Pos + 3));
    +handle_input("\e[C" ++ Rest, Pos) ->
         %% right key
    -    handle_input(Rest, min(8, Pos + 1));
    -handle_input("\e[D" ++ Rest, Pos) ->
    +    handle_input(Rest, min(8, Pos + 1));
    +handle_input("\e[D" ++ Rest, Pos) ->
         %% left key
    -    handle_input(Rest, max(0, Pos - 1));
    -handle_input("q" ++ _, _State) ->
    +    handle_input(Rest, max(0, Pos - 1));
    +handle_input("q" ++ _, _State) ->
         stop;
    -handle_input([_ | T], State) ->
    -    handle_input(T, State);
    -handle_input([], State) ->
    +handle_input([_ | T], State) ->
    +    handle_input(T, State);
    +handle_input([], State) ->
         State.

    Note that when using io:get_chars/2 with the shell set in {noshell, raw} mode it will return as soon as any data is available. The number of characters is the maximum number that will be returned. We use 1024 here to make sure that @@ -110,24 +110,24 @@ %% \b = Move cursor left %% \e[C = Move cursor right %% \n = Move cursor down -clear_selection(Pos) -> - [set_position(Pos), +clear_selection(Pos) -> + [set_position(Pos), " ","\b\b\b\b\b\b\b\n", " \e[C\e[C\e[C\e[C\e[C ", - "\b\b\b\b\b\b\b\n"," "]. + "\b\b\b\b\b\b\b\n"," "]. -draw_selection(Pos) -> - [set_position(Pos), +draw_selection(Pos) -> + [set_position(Pos), "┌─────┐","\b\b\b\b\b\b\b\n", "│\e[C\e[C\e[C\e[C\e[C│", - "\b\b\b\b\b\b\b\n","└─────┘"]. + "\b\b\b\b\b\b\b\n","└─────┘"]. %% Set the cursor position to be at the top %% left of the field of the given position -set_position(Pos) -> - Row = 6 + (Pos div 3) * 4, - Col = 7 + (Pos rem 3) * 8, - io_lib:format("\e[~p;~pH",[Row, Col]).

    Now we have a program where we can move the marker around the board. +set_position(Pos) -> + Row = 6 + (Pos div 3) * 4, + Col = 7 + (Pos rem 3) * 8, + io_lib:format("\e[~p;~pH",[Row, Col]).

    Now we have a program where we can move the marker around the board. To complete the game we need to add some state so that we know which squares are marked and whos turn it is. You can find the final solution in tic-tac-toe.es.

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/timer.xhtml differs (HTML document, ASCII text, with very long lines (1427)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/timer.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/timer.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -34,15 +34,15 @@ the Timer Module section in the Efficiency Guide.

    For more information on timers in Erlang in general, see the Timers section of the Time and Time Correction in Erlang -ERTS User's guide.

    Examples

    Example 1

    The following example shows how to print "Hello World!" in 5 seconds:

    1> timer:apply_after(5000, io, format, ["~nHello World!~n", []]).
    -{ok,TRef}
    +ERTS User's guide.

    Examples

    Example 1

    The following example shows how to print "Hello World!" in 5 seconds:

    1> timer:apply_after(5000, io, format, ["~nHello World!~n", []]).
    +{ok,TRef}
     Hello World!

    Example 2

    The following example shows a process performing a certain action, and if this -action is not completed within a certain limit, the process is killed:

    Pid = spawn(mod, fun, [foo, bar]),
    +action is not completed within a certain limit, the process is killed:

    Pid = spawn(mod, fun, [foo, bar]),
     %% If pid is not finished in 10 seconds, kill him
    -{ok, R} = timer:kill_after(timer:seconds(10), Pid),
    +{ok, R} = timer:kill_after(timer:seconds(10), Pid),
     ...
     %% We change our mind...
    -timer:cancel(R),
    +timer:cancel(R),
     ...

    Notes

    A timer can always be removed by calling cancel/1.

    An interval timer, that is, a timer created by evaluating any of the functions apply_interval/2, apply_interval/3, apply_interval/4, apply_repeatedly/2, apply_repeatedly/3, apply_repeatedly/4, @@ -63,20 +63,20 @@ process which set the timer about its completion, by sending it a done message.

    Using self/0 inside the timed function, the code below does not work as intended. The task gets done, but the done message gets sent to the wrong -process and is lost.

    1> timer:apply_after(1000, fun() -> do_something(), self() ! done end).
    -{ok,TRef}
    +process and is lost.

    1> timer:apply_after(1000, fun() -> do_something(), self() ! done end).
    +{ok,TRef}
     2> receive done -> done after 5000 -> timeout end.
     %% ... 5s pass...
     timeout

    The code below calls self/0 in the process which sets the timer and assigns it to a variable, which is then used in the function to send the done message to, -and so works as intended.

    1> Target = self()
    +and so works as intended.

    1> Target = self()
     <0.82.0>
    -2> timer:apply_after(1000, fun() -> do_something(), Target ! done end).
    -{ok,TRef}
    +2> timer:apply_after(1000, fun() -> do_something(), Target ! done end).
    +{ok,TRef}
     3> receive done -> done after 5000 -> timeout end.
     %% ... 1s passes...
    -done

    Another option is to pass the message target as a parameter to the function.

    1> timer:apply_after(1000, fun(Target) -> do_something(), Target ! done end, [self()]).
    -{ok,TRef}
    +done

    Another option is to pass the message target as a parameter to the function.

    1> timer:apply_after(1000, fun(Target) -> do_something(), Target ! done end, [self()]).
    +{ok,TRef}
     2> receive done -> done after 5000 -> timeout end.
     %% ... 1s passes...
     done
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/unicode_usage.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1740)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/unicode_usage.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/unicode_usage.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -201,20 +201,20 @@ iolists, where binaries and lists can be combined to represent a sequence of bytes. In the same way, the Unicode-aware modules often allow for combinations of binaries and lists, where the binaries have characters encoded in UTF-8 and -the lists contain such binaries or numbers representing Unicode code points:

    unicode_binary() = binary() with characters encoded in UTF-8 coding standard
    +the lists contain such binaries or numbers representing Unicode code points:

    unicode_binary() = binary() with characters encoded in UTF-8 coding standard
     
    -chardata() = charlist() | unicode_binary()
    +chardata() = charlist() | unicode_binary()
     
    -charlist() = maybe_improper_list(char() | unicode_binary() | charlist(),
    -  unicode_binary() | nil())

    The module unicode even supports similar mixes with binaries containing +charlist() = maybe_improper_list(char() | unicode_binary() | charlist(), + unicode_binary() | nil())

    The module unicode even supports similar mixes with binaries containing other encodings than UTF-8, but that is a special case to allow for conversions -to and from external data:

    external_unicode_binary() = binary() with characters coded in a user-specified
    -  Unicode encoding other than UTF-8 (UTF-16 or UTF-32)
    +to and from external data:

    external_unicode_binary() = binary() with characters coded in a user-specified
    +  Unicode encoding other than UTF-8 (UTF-16 or UTF-32)
     
    -external_chardata() = external_charlist() | external_unicode_binary()
    +external_chardata() = external_charlist() | external_unicode_binary()
     
    -external_charlist() = maybe_improper_list(char() | external_unicode_binary() |
    -  external_charlist(), external_unicode_binary() | nil())

    Basic Language Support

    As from Erlang/OTP R16, Erlang source files can be +external_charlist() = maybe_improper_list(char() | external_unicode_binary() | + external_charlist(), external_unicode_binary() | nil())

    Basic Language Support

    As from Erlang/OTP R16, Erlang source files can be written in UTF-8 or bytewise (latin1) encoding. For information about how to state the encoding of an Erlang source file, see the epp module. As from Erlang/OTP R16, strings and comments can be written using @@ -238,12 +238,12 @@ In the following example, the code point of a Cyrillic с is output:

    7> $с.
     1089

    Heuristic String Detection

    In certain output functions and in the output of return values in the shell, Erlang tries to detect string data in lists and binaries heuristically. -Typically you will see heuristic detection in a situation like this:

    1> [97,98,99].
    +Typically you will see heuristic detection in a situation like this:

    1> [97,98,99].
     "abc"
    -2> <<97,98,99>>.
    -<<"abc">>
    -3> <<195,165,195,164,195,182>>.
    -<<"åäö"/utf8>>

    Here the shell detects lists containing printable characters or binaries +2> <<97,98,99>>. +<<"abc">> +3> <<195,165,195,164,195,182>>. +<<"åäö"/utf8>>

    Here the shell detects lists containing printable characters or binaries containing printable characters in bytewise or UTF-8 encoding. But what is a printable character? One view is that anything the Unicode standard thinks is printable, is also printable according to the heuristic detection. The result is @@ -258,32 +258,32 @@ controls how heuristic string detection is done. More ranges are expected to be added in the future, enabling tailoring of the heuristics to the language and region relevant to the user.

    The following examples show the two startup options:

    $ erl +pc latin1
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> [1024].
    -[1024]
    -2> [1070,1085,1080,1082,1086,1076].
    -[1070,1085,1080,1082,1086,1076]
    -3> [229,228,246].
    +Eshell V5.10.1  (abort with ^G)
    +1> [1024].
    +[1024]
    +2> [1070,1085,1080,1082,1086,1076].
    +[1070,1085,1080,1082,1086,1076]
    +3> [229,228,246].
     "åäö"
    -4> <<208,174,208,189,208,184,208,186,208,190,208,180>>.
    -<<208,174,208,189,208,184,208,186,208,190,208,180>>
    -5> <<229/utf8,228/utf8,246/utf8>>.
    -<<"åäö"/utf8>>
    $ erl +pc unicode
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +4> <<208,174,208,189,208,184,208,186,208,190,208,180>>.
    +<<208,174,208,189,208,184,208,186,208,190,208,180>>
    +5> <<229/utf8,228/utf8,246/utf8>>.
    +<<"åäö"/utf8>>
    $ erl +pc unicode
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> [1024].
    +Eshell V5.10.1  (abort with ^G)
    +1> [1024].
     "Ѐ"
    -2> [1070,1085,1080,1082,1086,1076].
    +2> [1070,1085,1080,1082,1086,1076].
     "Юникод"
    -3> [229,228,246].
    +3> [229,228,246].
     "åäö"
    -4> <<208,174,208,189,208,184,208,186,208,190,208,180>>.
    -<<"Юникод"/utf8>>
    -5> <<229/utf8,228/utf8,246/utf8>>.
    -<<"åäö"/utf8>>

    In the examples, you can see that the default Erlang shell interprets only +4> <<208,174,208,189,208,184,208,186,208,190,208,180>>. +<<"Юникод"/utf8>> +5> <<229/utf8,228/utf8,246/utf8>>. +<<"åäö"/utf8>>

    In the examples, you can see that the default Erlang shell interprets only characters from the ISO Latin1 range as printable and only detects lists or binaries with those "printable" characters as containing string data. The valid UTF-8 binary containing the Russian word "Юникод", is not printed as a string. @@ -291,17 +291,17 @@ outputs anything containing printable Unicode data (in binaries, either UTF-8 or bytewise encoded) as string data.

    These heuristics are also used by io:format/2, io_lib:format/2, and friends when modifier t is used with ~p or ~P:

    $ erl +pc latin1
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> io:format("~tp~n",[{<<"åäö">>, <<"åäö"/utf8>>, <<208,174,208,189,208,184,208,186,208,190,208,180>>}]).
    -{<<"åäö">>,<<"åäö"/utf8>>,<<208,174,208,189,208,184,208,186,208,190,208,180>>}
    +Eshell V5.10.1  (abort with ^G)
    +1> io:format("~tp~n",[{<<"åäö">>, <<"åäö"/utf8>>, <<208,174,208,189,208,184,208,186,208,190,208,180>>}]).
    +{<<"åäö">>,<<"åäö"/utf8>>,<<208,174,208,189,208,184,208,186,208,190,208,180>>}
     ok
    $ erl +pc unicode
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> io:format("~tp~n",[{<<"åäö">>, <<"åäö"/utf8>>, <<208,174,208,189,208,184,208,186,208,190,208,180>>}]).
    -{<<"åäö">>,<<"åäö"/utf8>>,<<"Юникод"/utf8>>}
    +Eshell V5.10.1  (abort with ^G)
    +1> io:format("~tp~n",[{<<"åäö">>, <<"åäö"/utf8>>, <<208,174,208,189,208,184,208,186,208,190,208,180>>}]).
    +{<<"åäö">>,<<"åäö"/utf8>>,<<"Юникод"/utf8>>}
     ok

    Notice that this only affects heuristic interpretation of lists and binaries on output. For example, the ~ts format sequence always outputs a valid list of characters, regardless of the +pc setting, as the programmer has explicitly @@ -318,19 +318,19 @@ capable of. There is no portable way for Erlang to ask the terminal about its UTF-8 capacity, we have to rely on the language and character type settings.

    To investigate what Erlang thinks about the terminal, the call io:getopts() can be used when the shell is started:

    $ LC_CTYPE=en_US.ISO-8859-1 erl
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> lists:keyfind(encoding, 1, io:getopts()).
    -{encoding,latin1}
    -2> q().
    +Eshell V5.10.1  (abort with ^G)
    +1> lists:keyfind(encoding, 1, io:getopts()).
    +{encoding,latin1}
    +2> q().
     ok
     $ LC_CTYPE=en_US.UTF-8 erl
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> lists:keyfind(encoding, 1, io:getopts()).
    -{encoding,unicode}
    +Eshell V5.10.1  (abort with ^G)
    +1> lists:keyfind(encoding, 1, io:getopts()).
    +{encoding,unicode}
     2>

    When (finally?) everything is in order with the locale settings, fonts. and the terminal emulator, you have probably found a way to input characters in the script you desire. For testing, the simplest way is to add some keyboard @@ -343,14 +343,14 @@ easily if you are not used to this. For example, entering commands using a Cyrillic character set is not easily done in the Erlang shell.

    Now you are set up for some Unicode input and output. The simplest thing to do is to enter a string in the shell:

    $ erl
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> lists:keyfind(encoding, 1, io:getopts()).
    -{encoding,unicode}
    +Eshell V5.10.1  (abort with ^G)
    +1> lists:keyfind(encoding, 1, io:getopts()).
    +{encoding,unicode}
     2> "Юникод".
     "Юникод"
    -3> io:format("~ts~n", [v(2)]).
    +3> io:format("~ts~n", [v(2)]).
     Юникод
     ok
     4>

    While strings can be input as Unicode characters, the language elements are @@ -377,10 +377,10 @@ charlist() represented by it.

    #!/usr/bin/env escript
     %%! -kernel standard_io_encoding latin1
     
    -main(_) ->
    -  {ok, Char} = file:read_line(standard_io),
    -  ok = file:write(standard_io, string:trim(Char)),
    -  ok = file:write(standard_io, io_lib:format(": ~w~n",[string:trim(Char)])),
    +main(_) ->
    +  {ok, Char} = file:read_line(standard_io),
    +  ok = file:write(standard_io, string:trim(Char)),
    +  ok = file:write(standard_io, io_lib:format(": ~w~n",[string:trim(Char)])),
       ok.
    $ escript test.es
     ξ
     ξ: [206,190]

    ξ would normally be represented as the integer 958, but since we are using @@ -580,13 +580,13 @@ example {encoding,utf8}).

  • Functions reading Erlang syntax from files recognize the coding: comment and can therefore handle Unicode data on input. When writing Erlang terms to a file, you are advised to insert such comments when applicable:

    $ erl +fna +pc unicode
    -Erlang R16B (erts-5.10.1) [source]  [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source]  [async-threads:0] [hipe] [kernel-poll:false]
     
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/unicode.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1586))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/unicode.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/unicode.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -949,13 +949,13 @@
     the first part of a (so far) valid UTF character.

    If one UTF character is split over two consecutive binaries in the Data, the conversion succeeds. This means that a character can be decoded from a range of binaries as long as the whole range is specified as input without errors -occurring.

    Example:

    decode_data(Data) ->
    -   case unicode:characters_to_list(Data,unicode) of
    -      {incomplete,Encoded, Rest} ->
    -            More = get_some_more_data(),
    -            Encoded ++ decode_data([Rest, More]);
    -      {error,Encoded,Rest} ->
    -            handle_error(Encoded,Rest);
    +occurring.

    Example:

    decode_data(Data) ->
    +   case unicode:characters_to_list(Data,unicode) of
    +      {incomplete,Encoded, Rest} ->
    +            More = get_some_more_data(),
    +            Encoded ++ decode_data([Rest, More]);
    +      {error,Encoded,Rest} ->
    +            handle_error(Encoded,Rest);
           List ->
                 List
        end.

    However, bit strings that are not whole bytes are not allowed, so a UTF @@ -990,8 +990,8 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form -of canonical equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    4> unicode:characters_to_nfc_binary([<<"abc..a">>,[778],$a,[776],$o,[776]]).
    -<<"abc..åäö"/utf8>>
    +of canonical equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    4> unicode:characters_to_nfc_binary([<<"abc..a">>,[778],$a,[776],$o,[776]]).
    +<<"abc..åäö"/utf8>>
    @@ -1022,7 +1022,7 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form -of canonical equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    3> unicode:characters_to_nfc_list([<<"abc..a">>,[778],$a,[776],$o,[776]]).
    +of canonical equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    3> unicode:characters_to_nfc_list([<<"abc..a">>,[778],$a,[776],$o,[776]]).
     "abc..åäö"
    @@ -1054,8 +1054,8 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form -of canonical equivalent Decomposed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    2> unicode:characters_to_nfd_binary("abc..åäö").
    -<<97,98,99,46,46,97,204,138,97,204,136,111,204,136>>
    +of canonical equivalent Decomposed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    2> unicode:characters_to_nfd_binary("abc..åäö").
    +<<97,98,99,46,46,97,204,138,97,204,136,111,204,136>>
    @@ -1086,8 +1086,8 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form -of canonical equivalent Decomposed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    1> unicode:characters_to_nfd_list("abc..åäö").
    -[97,98,99,46,46,97,778,97,776,111,776]
    +of canonical equivalent Decomposed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    1> unicode:characters_to_nfd_list("abc..åäö").
    +[97,98,99,46,46,97,778,97,776,111,776]
    @@ -1118,8 +1118,8 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form -of compatibly equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    4> unicode:characters_to_nfkc_binary([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]).
    -<<"abc..åäö32"/utf8>>
    +of compatibly equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    4> unicode:characters_to_nfkc_binary([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]).
    +<<"abc..åäö32"/utf8>>
    @@ -1150,7 +1150,7 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form -of compatibly equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    3> unicode:characters_to_nfkc_list([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]).
    +of compatibly equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    3> unicode:characters_to_nfkc_list([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]).
     "abc..åäö32"
    @@ -1183,8 +1183,8 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form of compatibly equivalent Decomposed characters according to the Unicode -standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    2> unicode:characters_to_nfkd_binary(["abc..åäö",[65299,65298]]).
    -<<97,98,99,46,46,97,204,138,97,204,136,111,204,136,51,50>>
    +standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    2> unicode:characters_to_nfkd_binary(["abc..åäö",[65299,65298]]).
    +<<97,98,99,46,46,97,204,138,97,204,136,111,204,136,51,50>>
    @@ -1216,8 +1216,8 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form of compatibly equivalent Decomposed characters according to the Unicode -standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    1> unicode:characters_to_nfkd_list(["abc..åäö",[65299,65298]]).
    -[97,98,99,46,46,97,778,97,776,111,776,51,50]
    +standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    1> unicode:characters_to_nfkd_list(["abc..åäö",[65299,65298]]).
    +[97,98,99,46,46,97,778,97,776,111,776,51,50]
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/uri_string_usage.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1070)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/uri_string_usage.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/uri_string_usage.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -68,19 +68,19 @@ to explain this by an example.

    Let's say that we would like to create the following URI and send it over the network: http://cities/örebro?foo bar. This is not a valid URI as it contains characters that are not allowed in a URI such as "ö" and the space. We can -verify this by parsing the URI:

      1> uri_string:parse("http://cities/örebro?foo bar").
    -  {error,invalid_uri,":"}

    The URI parser tries all possible combinations to interpret the input and fails +verify this by parsing the URI:

      1> uri_string:parse("http://cities/örebro?foo bar").
    +  {error,invalid_uri,":"}

    The URI parser tries all possible combinations to interpret the input and fails at the last attempt when it encounters the colon character ":". Note, that the inital fault occurs when the parser attempts to interpret the character "ö" and after a failure back-tracks to the point where it has another possible parsing alternative.

    The proper way to solve this problem is to use uri_string:recompose/1 with a -uri_map() as input:

      2> uri_string:recompose(#{scheme => "http", host => "cities", path => "/örebro",
    -  query => "foo bar"}).
    +uri_map() as input:

      2> uri_string:recompose(#{scheme => "http", host => "cities", path => "/örebro",
    +  query => "foo bar"}).
       "http://cities/%C3%B6rebro?foo%20bar"

    The result is a valid URI where all the special characters are encoded as defined by the standard. Applying uri_string:parse/1 and -uri_string:percent_decode/1 on the URI returns the original input:

      3> uri_string:percent_decode(uri_string:parse("http://cities/%C3%B6rebro?foo%20bar")).
    -  #{host => "cities",path => "/örebro",query => "foo bar",
    -  scheme => "http"}

    This symmetric property is heavily used in our property test suite.

    Percent-encoding

    As you have seen in the previous chapter, a standard URI can only contain a +uri_string:percent_decode/1 on the URI returns the original input:

      3> uri_string:percent_decode(uri_string:parse("http://cities/%C3%B6rebro?foo%20bar")).
    +  #{host => "cities",path => "/örebro",query => "foo bar",
    +  scheme => "http"}

    This symmetric property is heavily used in our property test suite.

    Percent-encoding

    As you have seen in the previous chapter, a standard URI can only contain a strict subset of the US ASCII character set, moreover the allowed set of characters is not the same in the different URI components. Percent-encoding is a mechanism to represent a data octet in a component when that octet's @@ -97,27 +97,27 @@ question the library provides a utility function, uri_string:allowed_characters/0, that lists the allowed set of characters in each major URI component, and also in the -most important standard character sets.

        1> uri_string:allowed_characters().
    -    [{scheme,
    -     "+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"},
    -    {userinfo,
    -     "!$%&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    -    {host,
    -     "!$&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    -    {ipv4,".0123456789"},
    -    {ipv6,".0123456789:ABCDEFabcdef"},
    -    {regname,
    -     "!$%&'()*+,-.0123456789;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    -    {path,
    -     "!$%&'()*+,-./0123456789:;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    -    {query,
    -     "!$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    -    {fragment,
    -     "!$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    -    {reserved,"!#$&'()*+,/:;=?@[]"},
    -    {unreserved,
    -     "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"}]

    If a URI component has a character that is not allowed, it will be -percent-encoded when the URI is produced:

        2> uri_string:recompose(#{scheme => "https", host => "local#host", path => ""}).
    +most important standard character sets.

        1> uri_string:allowed_characters().
    +    [{scheme,
    +     "+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"},
    +    {userinfo,
    +     "!$%&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    +    {host,
    +     "!$&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    +    {ipv4,".0123456789"},
    +    {ipv6,".0123456789:ABCDEFabcdef"},
    +    {regname,
    +     "!$%&'()*+,-.0123456789;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    +    {path,
    +     "!$%&'()*+,-./0123456789:;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    +    {query,
    +     "!$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    +    {fragment,
    +     "!$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    +    {reserved,"!#$&'()*+,/:;=?@[]"},
    +    {unreserved,
    +     "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"}]

    If a URI component has a character that is not allowed, it will be +percent-encoded when the URI is produced:

        2> uri_string:recompose(#{scheme => "https", host => "local#host", path => ""}).
         "https://local%23host"

    Consuming a URI containing percent-encoded triplets can take many steps. The following example shows how to handle an input URI that is not normalized and contains multiple percent-encoded triplets. First, the input @@ -129,32 +129,32 @@ You can try to normalize the input with uri_string:normalize/1. The normalize operation decodes those percent-encoded triplets that correspond to a character in the unreserved set. Normalization is a safe, idempotent operation that -converts a URI into its canonical form:

        4> uri_string:normalize("http://%6C%6Fcal%23host/%F6re%26bro%20").
    +converts a URI into its canonical form:

        4> uri_string:normalize("http://%6C%6Fcal%23host/%F6re%26bro%20").
         "http://local%23host/%F6re%26bro%20"
    -    5> uri_string:normalize("http://%6C%6Fcal%23host/%F6re%26bro%20", [return_map]).
    -    #{host => "local%23host",path => "/%F6re%26bro%20",
    -      scheme => "http"}

    There are still a few percent-encoded triplets left in the output. At this + 5> uri_string:normalize("http://%6C%6Fcal%23host/%F6re%26bro%20", [return_map]). + #{host => "local%23host",path => "/%F6re%26bro%20", + scheme => "http"}

    There are still a few percent-encoded triplets left in the output. At this point, when the URI is already parsed, it is safe to apply application specific decoding on the remaining character triplets. Erlang/OTP provides a function, uri_string:percent_decode/1 for raw percent decoding that you can use on the -host and path components, or on the whole map:

        6> uri_string:percent_decode("local%23host").
    +host and path components, or on the whole map:

        6> uri_string:percent_decode("local%23host").
         "local#host"
    -    7> uri_string:percent_decode("/%F6re%26bro%20").
    -    {error,invalid_utf8,<<"/öre&bro ">>}
    -    8> uri_string:percent_decode(#{host => "local%23host",path => "/%F6re%26bro%20",
    -    scheme => "http"}).
    -    {error,{invalid,{path,{invalid_utf8,<<"/öre&bro ">>}}}}

    The host was successfully decoded but the path contains at least one character + 7> uri_string:percent_decode("/%F6re%26bro%20"). + {error,invalid_utf8,<<"/öre&bro ">>} + 8> uri_string:percent_decode(#{host => "local%23host",path => "/%F6re%26bro%20", + scheme => "http"}). + {error,{invalid,{path,{invalid_utf8,<<"/öre&bro ">>}}}}

    The host was successfully decoded but the path contains at least one character with non-UTF-8 encoding. In order to be able to decode this, you have to make assumptions about the encoding used in these triplets. The most obvious choice is latin-1, so you can try uri_string:transcode/2, to transcode the path to -UTF-8 and run the percent-decode operation on the transcoded string:

        9> uri_string:transcode("/%F6re%26bro%20", [{in_encoding, latin1}]).
    +UTF-8 and run the percent-decode operation on the transcoded string:

        9> uri_string:transcode("/%F6re%26bro%20", [{in_encoding, latin1}]).
         "/%C3%B6re%26bro%20"
    -    10> uri_string:percent_decode("/%C3%B6re%26bro%20").
    +    10> uri_string:percent_decode("/%C3%B6re%26bro%20").
         "/öre&bro "

    It is important to emphasize that it is not safe to apply -uri_string:percent_decode/1 directly on an input URI:

        11> uri_string:percent_decode("http://%6C%6Fcal%23host/%C3%B6re%26bro%20").
    +uri_string:percent_decode/1 directly on an input URI:

        11> uri_string:percent_decode("http://%6C%6Fcal%23host/%C3%B6re%26bro%20").
         "http://local#host/öre&bro "
    -    12> uri_string:parse("http://local#host/öre&bro ").
    -    {error,invalid_uri,":"}

    Note

    Percent-encoding is implemented in uri_string:recompose/1 and it happens + 12> uri_string:parse("http://local#host/öre&bro "). + {error,invalid_uri,":"}

    Note

    Percent-encoding is implemented in uri_string:recompose/1 and it happens when converting a uri_map() into a uri_string(). Applying any percent-encoding directly on an input URI would not be safe just as in the case of /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/uri_string.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1060)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/uri_string.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/uri_string.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -479,11 +479,11 @@

    Composes a form-urlencoded QueryString based on a QueryList, a list of non-percent-encoded key-value pairs.

    Form-urlencoding is defined in section 4.10.21.6 of the HTML 5.2 specification and in section 4.10.22.6 of the HTML 5.0 -specification for non-UTF-8 encodings.

    See also the opposite operation dissect_query/1.

    Example:

    1> uri_string:compose_query([{"foo bar","1"},{"city","örebro"}]).
    +specification for non-UTF-8 encodings.

    See also the opposite operation dissect_query/1.

    Example:

    1> uri_string:compose_query([{"foo bar","1"},{"city","örebro"}]).
     "foo+bar=1&city=%C3%B6rebro"
    -2> uri_string:compose_query([{<<"foo bar">>,<<"1">>},
    -2> {<<"city">>,<<"örebro"/utf8>>}]).
    -<<"foo+bar=1&city=%C3%B6rebro">>
    +2>
    uri_string:compose_query([{<<"foo bar">>,<<"1">>}, +2> {<<"city">>,<<"örebro"/utf8>>}]). +<<"foo+bar=1&city=%C3%B6rebro">>
    @@ -526,12 +526,12 @@ ";" (U+003B) character.

    Bytes that are out of the range 0x2A, 0x2D, 0x2E, 0x30 to 0x39, 0x41 to 0x5A, 0x5F, 0x61 to 0x7A, are percent-encoded (U+0025 PERCENT SIGN character (%) followed by uppercase ASCII hex digits representing the hexadecimal value of the -byte).

    See also the opposite operation dissect_query/1.

    Example:

    1> uri_string:compose_query([{"foo bar","1"},{"city","örebro"}],
    -1> [{encoding, latin1}]).
    +byte).

    See also the opposite operation dissect_query/1.

    Example:

    1> uri_string:compose_query([{"foo bar","1"},{"city","örebro"}],
    +1> [{encoding, latin1}]).
     "foo+bar=1&city=%F6rebro"
    -2> uri_string:compose_query([{<<"foo bar">>,<<"1">>},
    -2> {<<"city">>,<<"東京"/utf8>>}], [{encoding, latin1}]).
    -<<"foo+bar=1&city=%26%2326481%3B%26%2320140%3B">>
    +2>
    uri_string:compose_query([{<<"foo bar">>,<<"1">>}, +2> {<<"city">>,<<"東京"/utf8>>}], [{encoding, latin1}]). +<<"foo+bar=1&city=%26%2326481%3B%26%2320140%3B">>
    @@ -567,11 +567,11 @@

    Dissects an urlencoded QueryString and returns a QueryList, a list of non-percent-encoded key-value pairs.

    Form-urlencoding is defined in section 4.10.21.6 of the HTML 5.2 specification and in section 4.10.22.6 of the HTML 5.0 -specification for non-UTF-8 encodings.

    See also the opposite operation compose_query/1.

    Example:

    1> uri_string:dissect_query("foo+bar=1&city=%C3%B6rebro").
    -[{"foo bar","1"},{"city","örebro"}]
    -2> uri_string:dissect_query(<<"foo+bar=1&city=%26%2326481%3B%26%2320140%3B">>).
    -[{<<"foo bar">>,<<"1">>},
    - {<<"city">>,<<230,157,177,228,186,172>>}]
    +specification for non-UTF-8 encodings.

    See also the opposite operation compose_query/1.

    Example:

    1> uri_string:dissect_query("foo+bar=1&city=%C3%B6rebro").
    +[{"foo bar","1"},{"city","örebro"}]
    +2> uri_string:dissect_query(<<"foo+bar=1&city=%26%2326481%3B%26%2320140%3B">>).
    +[{<<"foo bar">>,<<"1">>},
    + {<<"city">>,<<230,157,177,228,186,172>>}]
    @@ -605,14 +605,14 @@

    Transforms an URI into a normalized form using Syntax-Based Normalization as defined by RFC 3986.

    This function implements case normalization, percent-encoding normalization, path segment normalization and scheme based normalization for HTTP(S) with basic -support for FTP, SSH, SFTP and TFTP.

    Example:

    1> uri_string:normalize("/a/b/c/./../../g").
    +support for FTP, SSH, SFTP and TFTP.

    Example:

    1> uri_string:normalize("/a/b/c/./../../g").
     "/a/g"
    -2> uri_string:normalize(<<"mid/content=5/../6">>).
    -<<"mid/6">>
    -3> uri_string:normalize("http://localhost:80").
    +2> uri_string:normalize(<<"mid/content=5/../6">>).
    +<<"mid/6">>
    +3> uri_string:normalize("http://localhost:80").
     "http://localhost/"
    -4> uri_string:normalize(#{scheme => "http",port => 80,path => "/a/b/c/./../../g",
    -4> host => "localhost-örebro"}).
    +4> uri_string:normalize(#{scheme => "http",port => 80,path => "/a/b/c/./../../g",
    +4> host => "localhost-örebro"}).
     "http://localhost-%C3%B6rebro/a/g"
    @@ -649,15 +649,15 @@

    Same as normalize/1 but with an additional Options parameter, that controls whether the normalized URI shall be returned as an -uri_map().

    There is one supported option: return_map.

    Example:

    1> uri_string:normalize("/a/b/c/./../../g", [return_map]).
    -#{path => "/a/g"}
    -2> uri_string:normalize(<<"mid/content=5/../6">>, [return_map]).
    -#{path => <<"mid/6">>}
    -3> uri_string:normalize("http://localhost:80", [return_map]).
    -#{scheme => "http",path => "/",host => "localhost"}
    -4> uri_string:normalize(#{scheme => "http",port => 80,path => "/a/b/c/./../../g",
    -4> host => "localhost-örebro"}, [return_map]).
    -#{scheme => "http",path => "/a/g",host => "localhost-örebro"}
    +uri_map().

    There is one supported option: return_map.

    Example:

    1> uri_string:normalize("/a/b/c/./../../g", [return_map]).
    +#{path => "/a/g"}
    +2> uri_string:normalize(<<"mid/content=5/../6">>, [return_map]).
    +#{path => <<"mid/6">>}
    +3> uri_string:normalize("http://localhost:80", [return_map]).
    +#{scheme => "http",path => "/",host => "localhost"}
    +4> uri_string:normalize(#{scheme => "http",port => 80,path => "/a/b/c/./../../g",
    +4> host => "localhost-örebro"}, [return_map]).
    +#{scheme => "http",path => "/a/g",host => "localhost-örebro"}
    @@ -689,14 +689,14 @@

    Parses an RFC 3986 compliant uri_string/0 into a uri_map/0, that holds the parsed components of the -URI. If parsing fails, an error tuple is returned.

    See also the opposite operation recompose/1.

    Example:

    1> uri_string:parse("foo://user@example.com:8042/over/there?name=ferret#nose").
    -#{fragment => "nose",host => "example.com",
    +URI. If parsing fails, an error tuple is returned.

    See also the opposite operation recompose/1.

    Example:

    1> uri_string:parse("foo://user@example.com:8042/over/there?name=ferret#nose").
    +#{fragment => "nose",host => "example.com",
       path => "/over/there",port => 8042,query => "name=ferret",
    -  scheme => foo,userinfo => "user"}
    -2> uri_string:parse(<<"foo://user@example.com:8042/over/there?name=ferret">>).
    -#{host => <<"example.com">>,path => <<"/over/there">>,
    -  port => 8042,query => <<"name=ferret">>,scheme => <<"foo">>,
    -  userinfo => <<"user">>}
    +
    scheme => foo,userinfo => "user"} +2> uri_string:parse(<<"foo://user@example.com:8042/over/there?name=ferret">>). +#{host => <<"example.com">>,path => <<"/over/there">>, + port => 8042,query => <<"name=ferret">>,scheme => <<"foo">>, + userinfo => <<"user">>}
    @@ -736,16 +736,16 @@

    Decodes all percent-encoded triplets in the input that can be both a uri_string/0 and a uri_map/0.

    Note, that this function performs raw decoding and it shall be used on already parsed URI components. Applying this function directly on a standard URI can -effectively change it.

    If the input encoding is not UTF-8, an error tuple is returned.

    Example:

    1> uri_string:percent_decode(#{host => "localhost-%C3%B6rebro",path => [],
    -1> scheme => "http"}).
    -#{host => "localhost-örebro",path => [],scheme => "http"}
    -2> uri_string:percent_decode(<<"%C3%B6rebro">>).
    -<<"örebro"/utf8>>

    Warning

    Using uri_string:percent_decode/1 directly on a URI is not safe. This +effectively change it.

    If the input encoding is not UTF-8, an error tuple is returned.

    Example:

    1> uri_string:percent_decode(#{host => "localhost-%C3%B6rebro",path => [],
    +1> scheme => "http"}).
    +#{host => "localhost-örebro",path => [],scheme => "http"}
    +2> uri_string:percent_decode(<<"%C3%B6rebro">>).
    +<<"örebro"/utf8>>

    Warning

    Using uri_string:percent_decode/1 directly on a URI is not safe. This example shows, that after each consecutive application of the function the -resulting URI will be changed. None of these URIs refer to the same resource.

    3> uri_string:percent_decode(<<"http://local%252Fhost/path">>).
    -<<"http://local%2Fhost/path">>
    -4> uri_string:percent_decode(<<"http://local%2Fhost/path">>).
    -<<"http://local/host/path">>
    +resulting URI will be changed. None of these URIs refer to the same resource.

    3> uri_string:percent_decode(<<"http://local%252Fhost/path">>).
    +<<"http://local%2Fhost/path">>
    +4> uri_string:percent_decode(<<"http://local%2Fhost/path">>).
    +<<"http://local/host/path">>
    @@ -777,10 +777,10 @@

    Replaces characters out of unreserved set with their percent encoded equivalents.

    Unreserved characters defined in -RFC 3986 are not quoted.

    Example:

    1> uri_string:quote("SomeId/04").
    +RFC 3986 are not quoted.

    Example:

    1> uri_string:quote("SomeId/04").
     "SomeId%2F04"
    -2> uri_string:quote(<<"SomeId/04">>).
    -<<"SomeId%2F04">>

    Warning

    Function is not aware about any URI component context and should not be used +2> uri_string:quote(<<"SomeId/04">>). +<<"SomeId%2F04">>

    Warning

    Function is not aware about any URI component context and should not be used on whole URI. If applied more than once on the same data, might produce unexpected results.

    @@ -814,10 +814,10 @@

    Same as quote/1, but Safe allows user to provide a list of -characters to be protected from encoding.

    Example:

    1> uri_string:quote("SomeId/04", "/").
    +characters to be protected from encoding.

    Example:

    1> uri_string:quote("SomeId/04", "/").
     "SomeId/04"
    -2> uri_string:quote(<<"SomeId/04">>, "/").
    -<<"SomeId/04">>

    Warning

    Function is not aware about any URI component context and should not be used +2> uri_string:quote(<<"SomeId/04">>, "/"). +<<"SomeId/04">>

    Warning

    Function is not aware about any URI component context and should not be used on whole URI. If applied more than once on the same data, might produce unexpected results.

    @@ -851,13 +851,13 @@

    Creates an RFC 3986 compliant URIString (percent-encoded), based on the components of URIMap. If the -URIMap is invalid, an error tuple is returned.

    See also the opposite operation parse/1.

    Example:

    1> URIMap = #{fragment => "nose", host => "example.com", path => "/over/there",
    -1> port => 8042, query => "name=ferret", scheme => "foo", userinfo => "user"}.
    -#{fragment => "nose",host => "example.com",
    +URIMap is invalid, an error tuple is returned.

    See also the opposite operation parse/1.

    Example:

    1> URIMap = #{fragment => "nose", host => "example.com", path => "/over/there",
    +1> port => 8042, query => "name=ferret", scheme => "foo", userinfo => "user"}.
    +#{fragment => "nose",host => "example.com",
       path => "/over/there",port => 8042,query => "name=ferret",
    -  scheme => "foo",userinfo => "user"}
    +  scheme => "foo",userinfo => "user"}
     
    -2> uri_string:recompose(URIMap).
    +2> uri_string:recompose(URIMap).
     "foo://example.com:8042/over/there?name=ferret#nose"
    @@ -894,13 +894,13 @@

    Convert a RefURI reference that might be relative to a given base URI into the parsed components of the reference's target, which can then be recomposed to -form the target URI.

    Example:

    1> uri_string:resolve("/abs/ol/ute", "http://localhost/a/b/c?q").
    +form the target URI.

    Example:

    1> uri_string:resolve("/abs/ol/ute", "http://localhost/a/b/c?q").
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/zip.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (2139))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/zip.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/zip.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -685,29 +685,29 @@
     archive. The iteration can be ended prematurely in a controlled manner by
     throwing an exception.

    Example:

    > Name = "dummy.zip".
     "dummy.zip"
    -> {ok, {Name, Bin}} = zip:create(Name, [{"foo", <<"FOO">>}, {"bar", <<"BAR">>}], [memory]).
    -{ok,{"dummy.zip",
    -     <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0,
    -       0,0,3,0,0,...>>}}
    -> {ok, FileSpec} = zip:foldl(fun(N, I, B, Acc) -> [{N, B(), I()} | Acc] end, [], {Name, Bin}).
    -{ok,[{"bar",<<"BAR">>,
    -      {file_info,3,regular,read_write,
    -                 {{2010,3,1},{19,2,10}},
    -                 {{2010,3,1},{19,2,10}},
    -                 {{2010,3,1},{19,2,10}},
    -                 54,1,0,0,0,0,0}},
    -     {"foo",<<"FOO">>,
    -      {file_info,3,regular,read_write,
    -                 {{2010,3,1},{19,2,10}},
    -                 {{2010,3,1},{19,2,10}},
    -                 {{2010,3,1},{19,2,10}},
    -                 54,1,0,0,0,0,0}}]}
    -> {ok, {Name, Bin}} = zip:create(Name, lists:reverse(FileSpec), [memory]).
    -{ok,{"dummy.zip",
    -     <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0,
    -       0,0,3,0,0,...>>}}
    -> catch zip:foldl(fun("foo", _, B, _) -> throw(B()); (_,_,_,Acc) -> Acc end, [], {Name, Bin}).
    -<<"FOO">>
    +>
    {ok, {Name, Bin}} = zip:create(Name, [{"foo", <<"FOO">>}, {"bar", <<"BAR">>}], [memory]). +{ok,{"dummy.zip", + <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0, + 0,0,3,0,0,...>>}} +> {ok, FileSpec} = zip:foldl(fun(N, I, B, Acc) -> [{N, B(), I()} | Acc] end, [], {Name, Bin}). +{ok,[{"bar",<<"BAR">>, + {file_info,3,regular,read_write, + {{2010,3,1},{19,2,10}}, + {{2010,3,1},{19,2,10}}, + {{2010,3,1},{19,2,10}}, + 54,1,0,0,0,0,0}}, + {"foo",<<"FOO">>, + {file_info,3,regular,read_write, + {{2010,3,1},{19,2,10}}, + {{2010,3,1},{19,2,10}}, + {{2010,3,1},{19,2,10}}, + 54,1,0,0,0,0,0}}]} +> {ok, {Name, Bin}} = zip:create(Name, lists:reverse(FileSpec), [memory]). +{ok,{"dummy.zip", + <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0, + 0,0,3,0,0,...>>}} +> catch zip:foldl(fun("foo", _, B, _) -> throw(B()); (_,_,_,Acc) -> Acc end, [], {Name, Bin}). +<<"FOO">>
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/zstd.xhtml differs (HTML document, ASCII text, with very long lines (1144)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/zstd.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib.epub/OEBPS/zstd.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -25,25 +25,25 @@

    Zstandard compression interface.

    This module provides an API for the Zstandard library (www.zstd.net). It is used to compress and decompress data and offers the same compression ratio as zlib but at a lower CPU cost.

    Example:

    1> Data = ~"my data to be compressed".
    -2> Compressed = zstd:compress(Data).
    -3> zstd:decompress(Compressed).
    -[~"my data to be compressed"]

    If you are compressing or decompressing possibly large amounts of data, -it is also possible to do streamed compression/decompression.

    Example:

    1> Compress = fun F(Ctx, D) ->
    -                      case file:read(D, 5) of
    -                          {ok, Data} ->
    -                              {continue, C} = zstd:stream(Ctx, Data),
    -                              [C|F(Ctx, D)];
    +2> Compressed = zstd:compress(Data).
    +3> zstd:decompress(Compressed).
    +[~"my data to be compressed"]

    If you are compressing or decompressing possibly large amounts of data, +it is also possible to do streamed compression/decompression.

    Example:

    1> Compress = fun F(Ctx, D) ->
    +                      case file:read(D, 5) of
    +                          {ok, Data} ->
    +                              {continue, C} = zstd:stream(Ctx, Data),
    +                              [C|F(Ctx, D)];
                               eof ->
    -                              {done, C} = zstd:finish(Ctx, ""),
    +                              {done, C} = zstd:finish(Ctx, ""),
                                   C
                           end
                   end.
    -2> {ok, Ctx} = zstd:context(compress).
    -3> {ok, D} = file:open(File,[read,binary]).
    -4> Compressed = iolist_to_binary(Compress(Ctx, D)).
    -<<40,181,47,253,0,88,89,0,0,108,111,114,101,109,32,105,112,115,117,109>>
    -5> zstd:decompress(Compressed).
    -[~"lorem ipsum"]

    In all functions errors can be thrown, where Reason describes the error.

    Typical Reasons:

    • badarg - Bad argument.
    • zstd_error - An error generated by the Zstandard library.
    • not_on_controlling_process - The context was used by a process that +2> {ok, Ctx} = zstd:context(compress). +3> {ok, D} = file:open(File,[read,binary]). +4> Compressed = iolist_to_binary(Compress(Ctx, D)). +<<40,181,47,253,0,88,89,0,0,108,111,114,101,109,32,105,112,115,117,109>> +5> zstd:decompress(Compressed). +[~"lorem ipsum"]

    In all functions errors can be thrown, where Reason describes the error.

    Typical Reasons:

    • badarg - Bad argument.
    • zstd_error - An error generated by the Zstandard library.
    • not_on_controlling_process - The context was used by a process that did not create it.
    @@ -621,8 +621,8 @@ -

    Compress Data using the given compress_parameters/0 or the context/0.

    Example:

    1> zstd:compress("abc").
    -2> zstd:compress("abc", #{ compressionLevel => 20 }).
    +

    Compress Data using the given compress_parameters/0 or the context/0.

    Example:

    1> zstd:compress("abc").
    +2> zstd:compress("abc", #{ compressionLevel => 20 }).
    @@ -745,9 +745,9 @@ -

    Decompress Data using the given decompress_parameters/0 or the context/0.

    Example:

    1> Compressed = zstd:compress("abc").
    -2> zstd:decompress(Compressed).
    -[~"abc"]
    +

    Decompress Data using the given decompress_parameters/0 or the context/0.

    Example:

    1> Compressed = zstd:compress("abc").
    +2> zstd:decompress(Compressed).
    +[~"abc"]
    @@ -816,12 +816,12 @@ you can use get_dict_id/1 on the dictionary and compressed data, or just try to decompress as decompression will raise and exception if an incorrect dictionary is given.

    The compressionLevel set on a dictionary will override the compressionLevel -set in the context/0.

    Example:

    1> {ok, CDict} = zstd:dict(compress, Dict).
    -2> Data = lists:duplicate(100, 1).
    -[1, 1, 1 | _]
    -3> iolist_size(zstd:compress(Data)).
    +set in the context/0.

    Example:

    1> {ok, CDict} = zstd:dict(compress, Dict).
    +2> Data = lists:duplicate(100, 1).
    +[1, 1, 1 | _]
    +3> iolist_size(zstd:compress(Data)).
     17
    -4> iolist_size(zstd:compress(Data, #{ dictionary => CDict, dictIDFlag => false })).
    +4> iolist_size(zstd:compress(Data, #{ dictionary => CDict, dictIDFlag => false })).
     16

    As loading a dictionary can be a heavy operations, it is possible to create only a single dict/0 and provide it to multiple context/0.

    There is no API exposed in zstd to create a dictionary, instead use the zstd command line tool.

    @@ -855,11 +855,11 @@

    Finish compressing/decompressing data.

    This flushes all output buffers and resets the context/0 so -that it can be used for compressing/decompressing again.

    Example:

    1> {ok, DCtx} = zstd:context(decompress).
    -2> {continue, D1} = zstd:stream(DCtx, <<40,181,47,253,32>>).
    -3> {done, D2} = zstd:finish(DCtx, <<2,17,0,0,97,98>>).
    -4> iolist_to_binary([D1,D2]).
    -<<"ab">>
    +that it can be used for compressing/decompressing again.

    Example:

    1> {ok, DCtx} = zstd:context(decompress).
    +2> {continue, D1} = zstd:stream(DCtx, <<40,181,47,253,32>>).
    +3> {done, D2} = zstd:finish(DCtx, <<2,17,0,0,97,98>>).
    +4> iolist_to_binary([D1,D2]).
    +<<"ab">>
    @@ -889,10 +889,10 @@ -

    Get the dictionary ID of a dictionary or a frame.

    The dictionary ID 0 represents no dictionary.

    Example:

    1> {ok, CDict} = zstd:dict(compress, Dict).
    -2> zstd:get_dict_id(CDict).
    +

    Get the dictionary ID of a dictionary or a frame.

    The dictionary ID 0 represents no dictionary.

    Example:

    1> {ok, CDict} = zstd:dict(compress, Dict).
    +2> zstd:get_dict_id(CDict).
     1850243626
    -3> zstd:get_dict_id(zstd:compress("abc")).
    +3> zstd:get_dict_id(zstd:compress("abc")).
     0
    @@ -934,11 +934,11 @@

    Get header of a Zstandard compressed frame.

    A compressed Zstandard stream can consist of multiple frames. This function will read metadata from the first frame. This information -can be useful when debugging corrupted Zstandard streams.

    Example:

    1> Compressed = zstd:compress(~"abc").
    -2> zstd:get_frame_header(Compressed).
    -{ok,#{frameContentSize => 3,windowSize => 3,blockSizeMax => 3,
    +can be useful when debugging corrupted Zstandard streams.

    Example:

    1> Compressed = zstd:compress(~"abc").
    +2> zstd:get_frame_header(Compressed).
    +{ok,#{frameContentSize => 3,windowSize => 3,blockSizeMax => 3,
           frameType => 'ZSTD_frame',headerSize => 6,
    -      dictID => 0, checksumFlag => false}}
    +
    dictID => 0, checksumFlag => false}}
    @@ -972,13 +972,13 @@ which parameters are available and what each parameter does.

    Note that it is not possible to get the dictionary and pledgedSrcSize parameters using this API. Instead you can use get_dict_id/1 on the context/0 to get the id of the dictionary used. There is no way to -get the pledgedSrcSize.

    Returns ok on success, raises an error on failure.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    -{ok, _}
    -2> zstd:get_parameter(CCtx, compressionLevel).
    +get the pledgedSrcSize.

    Returns ok on success, raises an error on failure.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    +{ok, _}
    +2> zstd:get_parameter(CCtx, compressionLevel).
     3
    -3> zstd:set_parameter(CCtx, compressionLevel, 15).
    +3> zstd:set_parameter(CCtx, compressionLevel, 15).
     ok
    -4> zstd:get_parameter(CCtx, compressionLevel).
    +4> zstd:get_parameter(CCtx, compressionLevel).
     15
    @@ -1011,14 +1011,14 @@

    Reset a context while streaming data, returning it to its original state but keeping all parameters set.

    By resetting the state, the context can be re-used for other operations even -if it is in the middle of a (de)compression stream.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    -2> zstd:stream(CCtx, "a").
    -{continue, _}
    -3> zstd:reset(CCtx).
    +if it is in the middle of a (de)compression stream.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    +2> zstd:stream(CCtx, "a").
    +{continue, _}
    +3> zstd:reset(CCtx).
     ok
    -4> {done, Compressed} = zstd:finish(CCtx, "b").
    -5> zstd:decompress(Compressed).
    -[~"b"]
    +4>
    {done, Compressed} = zstd:finish(CCtx, "b"). +5> zstd:decompress(Compressed). +[~"b"]
    @@ -1049,14 +1049,14 @@

    Set a parameter on a context/0.

    See compress_parameters/0 and decompress_parameters/0 for details on -which parameters are available and what each parameter does.

    Returns ok on success, raises an error on failure.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    -{ok, _}
    -2> ok = zstd:set_parameter(CCtx, compressionLevel, 15).
    +which parameters are available and what each parameter does.

    Returns ok on success, raises an error on failure.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    +{ok, _}
    +2> ok = zstd:set_parameter(CCtx, compressionLevel, 15).
     ok
    -3> zstd:stream(CCtx, "abc").
    -{continue, _}
    -4> catch zstd:set_parameter(CCtx, dictionary, "abc").
    -{'EXIT', {{zstd_error, <<"Operation not authorized at current processing stage">>}, _}}
    +3>
    zstd:stream(CCtx, "abc"). +{continue, _} +4> catch zstd:set_parameter(CCtx, dictionary, "abc"). +{'EXIT', {{zstd_error, <<"Operation not authorized at current processing stage">>}, _}}
    @@ -1091,13 +1091,13 @@

    Compress or decompress a stream of data. The last stream of data should be called -with finish/2 to complete the compression/decompression.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib_app.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1971))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib_app.html	2026-08-21 04:00:31.176371268 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/stdlib_app.html	2026-08-21 04:00:31.176371268 +0000
    @@ -113,13 +113,13 @@
     prompt function takes the main prompt as its only parameter.

  • shell_saved_results = integer() >= 0 - Can be used to determine how many results are saved by the Erlang shell.

  • shell_session_slogan = string() | fun() -> string()) - The slogan printed when starting an Erlang shell. Example:

    $ erl -stdlib shell_session_slogan '"Test slogan"'
    -Erlang/OTP 26 [DEVELOPMENT] [erts-13.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
    +Erlang/OTP 26 [DEVELOPMENT] [erts-13.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]
     
     Test slogan
     1>
  • shell_slogan = string() | fun(() -> string()) - The slogan printed when starting the Erlang shell subsystem. Example:

    $ erl -stdlib shell_slogan '"Test slogan"'
     Test slogan
    -Eshell V13.0.2  (abort with ^G)
    +Eshell V13.0.2  (abort with ^G)
     1>

    The default is the return value of erlang:system_info(system_version).

  • shell_strings = boolean() - Can be used to determine how the Erlang shell outputs lists of integers.

  • shell_hints = boolean() - Can be used to enable/disable /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/string.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/string.html 2026-08-21 04:00:31.218371541 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/string.html 2026-08-21 04:00:31.219371548 +0000 @@ -114,14 +114,14 @@ expect UTF-8 binaries but not all functions verify that all binaries are encoded correctly.

    Unless otherwise specified the return value type is the same as the input type. That is, binary input returns binary output, list input returns a list output, -and mixed input can return a mixed output.

    1> string:trim("  sarah  ").
    +and mixed input can return a mixed output.

    1> string:trim("  sarah  ").
     "sarah"
    -2> string:trim(<<"  sarah  ">>).
    -<<"sarah">>
    -3> string:lexemes("foo bar", " ").
    -["foo","bar"]
    -4> string:lexemes(<<"foo bar">>, " ").
    -[<<"foo">>,<<"bar">>]

    This module has been reworked in Erlang/OTP 20 to handle unicode:chardata/0 +2> string:trim(<<" sarah ">>). +<<"sarah">> +3> string:lexemes("foo bar", " "). +["foo","bar"] +4> string:lexemes(<<"foo bar">>, " "). +[<<"foo">>,<<"bar">>]

    This module has been reworked in Erlang/OTP 20 to handle unicode:chardata/0 and operate on grapheme clusters. The old functions that only work on Latin-1 lists as input are still available but should not be used, they will be @@ -1031,7 +1031,7 @@

    Converts String to a case-agnostic comparable string. Function casefold/1 is preferred over lowercase/1 -when two strings are to be compared for equality. See also equal/4.

    Example:

    1> string:casefold("Ω and ẞ SHARP S").
    +when two strings are to be compared for equality. See also equal/4.

    Example:

    1> string:casefold("Ω and ẞ SHARP S").
     "ω and ss sharp s"
  • @@ -1063,9 +1063,9 @@

    Returns a string where any trailing \n or \r\n have been removed from -String.

    Example:

    182> string:chomp(<<"\nHello\n\n">>).
    -<<"\nHello">>
    -183> string:chomp("\nHello\r\r\n").
    +String.

    Example:

    182> string:chomp(<<"\nHello\n\n">>).
    +<<"\nHello">>
    +183> string:chomp("\nHello\r\r\n").
     "\nHello\r"
    @@ -1166,11 +1166,11 @@ nfc, nfd, nfkc, and -nfkd.

    Example:

    1> string:equal("åäö", <<"åäö"/utf8>>).
    +nfkd.

    Example:

    1> string:equal("åäö", <<"åäö"/utf8>>).
     true
    -2> string:equal("åäö", unicode:characters_to_nfd_binary("åäö")).
    +2> string:equal("åäö", unicode:characters_to_nfd_binary("åäö")).
     false
    -3> string:equal("åäö", unicode:characters_to_nfd_binary("ÅÄÖ"), true, nfc).
    +3> string:equal("åäö", unicode:characters_to_nfd_binary("ÅÄÖ"), true, nfc).
     true
    @@ -1236,13 +1236,13 @@

    Removes anything before SearchPattern in String and returns the remainder of the string or nomatch if SearchPattern is not found. Dir, which can be leading or trailing, indicates from which direction characters are to be -searched.

    Example:

    1> string:find("ab..cd..ef", ".").
    +searched.

    Example:

    1> string:find("ab..cd..ef", ".").
     "..cd..ef"
    -2> string:find(<<"ab..cd..ef">>, "..", trailing).
    -<<"..ef">>
    -3> string:find(<<"ab..cd..ef">>, "x", leading).
    +2> string:find(<<"ab..cd..ef">>, "..", trailing).
    +<<"..ef">>
    +3> string:find(<<"ab..cd..ef">>, "x", leading).
     nomatch
    -4> string:find("ab..cd..ef", "x", trailing).
    +4> string:find("ab..cd..ef", "x", trailing).
     nomatch
    @@ -1273,9 +1273,9 @@ -

    Returns true if String is the empty string, otherwise false.

    Example:

    1> string:is_empty("foo").
    +

    Returns true if String is the empty string, otherwise false.

    Example:

    1> string:is_empty("foo").
     false
    -2> string:is_empty(["",<<>>]).
    +2> string:is_empty(["",<<>>]).
     true
    @@ -1313,13 +1313,13 @@

    Returns a float between +0.0 and 1.0 representing the Jaro similarity between the given strings. Strings with a higher similarity will score closer -to 1.0, with +0.0 meaning no similarity and 1.0 meaning an exact match.

    Example:

    1> string:jaro_similarity("ditto", "ditto").
    +to 1.0, with +0.0 meaning no similarity and 1.0 meaning an exact match.

    Example:

    1> string:jaro_similarity("ditto", "ditto").
     1.0
    -2> string:jaro_similarity("foo", "bar").
    +2> string:jaro_similarity("foo", "bar").
     +0.0
    -3> string:jaro_similarity("michelle", "michael").
    +3> string:jaro_similarity("michelle", "michael").
     0.8690476190476191
    -4> string:jaro_similarity(<<"Édouard"/utf8>>, <<"Claude">>).
    +4> string:jaro_similarity(<<"Édouard"/utf8>>, <<"Claude">>).
     0.5317460317460317

    The Jaro distance between two strings can be calculated with JaroDistance = 1.0 - JaroSimilarity.

    @@ -1351,9 +1351,9 @@ -

    Returns the number of grapheme clusters in String.

    Example:

    1> string:length("ß↑e̊").
    +

    Returns the number of grapheme clusters in String.

    Example:

    1> string:length("ß↑e̊").
     3
    -2> string:length(<<195,159,226,134,145,101,204,138>>).
    +2> string:length(<<195,159,226,134,145,101,204,138>>).
     3
    @@ -1388,10 +1388,10 @@

    Returns a list of lexemes in String, separated by the grapheme clusters in SeparatorList.

    Notice that, as shown in this example, two or more adjacent separator graphemes clusters in String are treated as one. That is, there are no empty strings in -the resulting list of lexemes. See also split/3 which returns empty strings.

    Notice that [$\r,$\n] is one grapheme cluster.

    Example:

    1> string:lexemes("abc de̊fxxghix jkl\r\nfoo", "x e" ++ [[$\r,$\n]]).
    -["abc","de̊f","ghi","jkl","foo"]
    -2> string:lexemes(<<"abc de̊fxxghix jkl\r\nfoo"/utf8>>, "x e" ++ [$\r,$\n]).
    -[<<"abc">>,<<"de̊f"/utf8>>,<<"ghi">>,<<"jkl\r\nfoo">>]
    +the resulting list of lexemes. See also split/3 which returns empty strings.

    Notice that [$\r,$\n] is one grapheme cluster.

    Example:

    1> string:lexemes("abc de̊fxxghix jkl\r\nfoo", "x e" ++ [[$\r,$\n]]).
    +["abc","de̊f","ghi","jkl","foo"]
    +2> string:lexemes(<<"abc de̊fxxghix jkl\r\nfoo"/utf8>>, "x e" ++ [$\r,$\n]).
    +[<<"abc">>,<<"de̊f"/utf8>>,<<"ghi">>,<<"jkl\r\nfoo">>]
    @@ -1422,7 +1422,7 @@

    Converts String to lowercase.

    Notice that function casefold/1 should be used when converting a string to be -tested for equality.

    Example:

    2> string:lowercase(string:uppercase("Michał")).
    +tested for equality.

    Example:

    2> string:lowercase(string:uppercase("Michał")).
     "michał"
    @@ -1456,8 +1456,8 @@

    Returns the first codepoint in String and the rest of String in the tail. Returns an empty list if String is empty or an {error, String} tuple if the -next byte is invalid.

    Example:

    1> string:next_codepoint(unicode:characters_to_binary("e̊fg")).
    -[101|<<"̊fg"/utf8>>]
    +next byte is invalid.

    Example:

    1> string:next_codepoint(unicode:characters_to_binary("e̊fg")).
    +[101|<<"̊fg"/utf8>>]
    @@ -1491,8 +1491,8 @@

    Returns the first grapheme cluster in String and the rest of String in the tail. Returns an empty list if String is empty or an {error, String} tuple -if the next byte is invalid.

    Example:

    1> string:next_grapheme(unicode:characters_to_binary("e̊fg")).
    -["e̊"|<<"fg">>]
    +if the next byte is invalid.

    Example:

    1> string:next_grapheme(unicode:characters_to_binary("e̊fg")).
    +["e̊"|<<"fg">>]
    @@ -1527,7 +1527,7 @@

    Returns lexeme number N in String, where lexemes are separated by the -grapheme clusters in SeparatorList.

    Example:

    1> string:nth_lexeme("abc.de̊f.ghiejkl", 3, ".e").
    +grapheme clusters in SeparatorList.

    Example:

    1> string:nth_lexeme("abc.de̊f.ghiejkl", 3, ".e").
     "ghi"
    @@ -1625,11 +1625,11 @@

    Pads String to Length with grapheme cluster Char. Dir, which can be -leading, trailing, or both, indicates where the padding should be added.

    Example:

    1> string:pad(<<"He̊llö"/utf8>>, 8).
    -[<<72,101,204,138,108,108,195,182>>,32,32,32]
    -2> io:format("'~ts'~n",[string:pad("He̊llö", 8, leading)]).
    +leading, trailing, or both, indicates where the padding should be added.

    Example:

    1> string:pad(<<"He̊llö"/utf8>>, 8).
    +[<<72,101,204,138,108,108,195,182>>,32,32,32]
    +2> io:format("'~ts'~n",[string:pad("He̊llö", 8, leading)]).
     '   He̊llö'
    -3> io:format("'~ts'~n",[string:pad("He̊llö", 8, both)]).
    +3> io:format("'~ts'~n",[string:pad("He̊llö", 8, both)]).
     ' He̊llö  '
    @@ -1661,9 +1661,9 @@

    If Prefix is the prefix of String, removes it and returns the remainder of -String, otherwise returns nomatch.

    Example:

    1> string:prefix(<<"prefix of string">>, "pre").
    -<<"fix of string">>
    -2> string:prefix("pre", "prefix").
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/supervisor.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1036))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/supervisor.html	2026-08-21 04:00:31.253371769 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/supervisor.html	2026-08-21 04:00:31.252371763 +0000
    @@ -111,11 +111,11 @@
     left to right according to this list. When the supervisor is going to terminate,
     it first terminates its child processes in reversed start order, from right to
     left.

    Supervisor flags

    The supervisor properties are defined by the supervisor flags. The type -definition for the supervisor flags is as follows:

    sup_flags() = #{strategy => strategy(),           % optional
    -                intensity => non_neg_integer(),   % optional
    -                period => pos_integer(),          % optional
    -                hibernate_after => timeout(),     % optional, available since OTP 28.0
    -                auto_shutdown => auto_shutdown()} % optional

    Restart Strategies

    A supervisor can have one of the following restart strategies specified with +definition for the supervisor flags is as follows:

    sup_flags() = #{strategy => strategy(),           % optional
    +                intensity => non_neg_integer(),   % optional
    +                period => pos_integer(),          % optional
    +                hibernate_after => timeout(),     % optional, available since OTP 28.0
    +                auto_shutdown => auto_shutdown()} % optional

    Restart Strategies

    A supervisor can have one of the following restart strategies specified with the strategy key in the above map:

    • one_for_one - If one child process terminates and is to be restarted, only that child process is affected. This is the default restart strategy.

    • one_for_all - If one child process terminates and is to be restarted, all other child processes are terminated and then all child processes are @@ -161,13 +161,13 @@ this feature will also compile and run with older OTP versions.

      However, such applications, when compiled with an OTP version that predates the appearance of the automatic shutdown feature, will leak processes because the automatic shutdowns they rely on will not happen.

      It is up to implementors to take proper precautions if they expect that their -applications may be compiled with older OTP versions.

      Child specification

      The type definition of a child specification is as follows:

      child_spec() = #{id => child_id(),             % mandatory
      -                 start => mfargs(),            % mandatory
      -                 restart => restart(),         % optional
      -                 significant => significant(), % optional
      -                 shutdown => shutdown(),       % optional
      -                 type => worker(),             % optional
      -                 modules => modules()}         % optional

      The old tuple format is kept for backwards compatibility, see child_spec/0, +applications may be compiled with older OTP versions.

      Child specification

      The type definition of a child specification is as follows:

      child_spec() = #{id => child_id(),             % mandatory
      +                 start => mfargs(),            % mandatory
      +                 restart => restart(),         % optional
      +                 significant => significant(), % optional
      +                 shutdown => shutdown(),       % optional
      +                 type => worker(),             % optional
      +                 modules => modules()}         % optional

      The old tuple format is kept for backwards compatibility, see child_spec/0, but the map is preferred.

      • id is used to identify the child specification internally by the supervisor.

        The id key is mandatory.

        Notice that this identifier on occasion has been called "name". As far as possible, the terms "identifier" or "id" are now used but to keep backward compatibility, some occurences of "name" can still be found, for example in /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/terminal_interface.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/terminal_interface.html 2026-08-21 04:00:31.276371919 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/terminal_interface.html 2026-08-21 04:00:31.276371919 +0000 @@ -104,18 +104,18 @@ ║ │ │ ║ ║ │ │ ║ ║ │ │ ║ -╚═══════╧═══════╧═══════╝

    We will use the alternate screen buffer for our game so first we need to set that up:

    #href_anchor"nf">main(_Args) ->
    +╚═══════╧═══════╧═══════╝

    We will use the alternate screen buffer for our game so first we need to set that up:

    #href_anchor"nf">main(_Args) ->
         
    -    io:put_chars("\e[?1049h"), %% Enable alternate screen buffer
    -    io:put_chars("\e[?25l"), %% Hide the cursor
    -    draw_board(),
    -    timer:sleep(5000),
    -    io:put_chars("\e[?25h"), %% Show the cursor
    -    io:put_chars("\e[?1049l"), %% Disable alternate screen buffer
    -    ok.

    We then use the box drawing parts of Unicode to draw our board:

    draw_board() ->
    -    io:put_chars("\e[5;0H"), %% Move cursor to top left
    -    io:put_chars(
    -      ["     ╔═══════╤═══════╤═══════╗\r\n",
    +    io:put_chars("\e[?1049h"), %% Enable alternate screen buffer
    +    io:put_chars("\e[?25l"), %% Hide the cursor
    +    draw_board(),
    +    timer:sleep(5000),
    +    io:put_chars("\e[?25h"), %% Show the cursor
    +    io:put_chars("\e[?1049l"), %% Disable alternate screen buffer
    +    ok.

    We then use the box drawing parts of Unicode to draw our board:

    draw_board() ->
    +    io:put_chars("\e[5;0H"), %% Move cursor to top left
    +    io:put_chars(
    +      ["     ╔═══════╤═══════╤═══════╗\r\n",
            "     ║       │       │       ║\r\n",
            "     ║       │       │       ║     Place an X by pressing Enter\r\n",
            "     ║       │       │       ║\r\n",
    @@ -127,51 +127,51 @@
            "     ║       │       │       ║\r\n",
            "     ║       │       │       ║\r\n",
            "     ║       │       │       ║\r\n",
    -       "     ╚═══════╧═══════╧═══════╝\r\n"]),
    +       "     ╚═══════╧═══════╧═══════╝\r\n"]),
         ok.

    Let us add some interactivity to our game! To do that we need to change the shell from running in cooked to raw mode. This is done by calling shell:start_interactive({noshell, raw}). We can then use io:get_chars/2 to read key strokes from the user. The key strokes will be returned as ANSI escape codes, -so we will have need to handle the codes for up, down, left, right and enter.

    It could look something like this:

    main(_Args) ->
    -    ok = shell:start_interactive({noshell, raw}),
    +so we will have need to handle the codes for up, down, left, right and enter.

    It could look something like this:

    main(_Args) ->
    +    ok = shell:start_interactive({noshell, raw}),
         
    -    io:put_chars("\e[?1049h"), %% Enable alternate screen buffer
    -    io:put_chars("\e[?25l"), %% Hide the cursor
    -    draw_board(),
    -    loop(0),
    -    io:put_chars("\e[?25h"), %% Show the cursor
    -    io:put_chars("\e[?1049l"), %% Disable alternate screen buffer
    +    io:put_chars("\e[?1049h"), %% Enable alternate screen buffer
    +    io:put_chars("\e[?25l"), %% Hide the cursor
    +    draw_board(),
    +    loop(0),
    +    io:put_chars("\e[?25h"), %% Show the cursor
    +    io:put_chars("\e[?1049l"), %% Disable alternate screen buffer
         ok.
     
    -loop(Pos) ->
    -    io:put_chars(draw_selection(Pos)),
    +loop(Pos) ->
    +    io:put_chars(draw_selection(Pos)),
         %% Read at most 1024 characters from stdin.
    -    Chars = io:get_chars("", 1024),
    -    case handle_input(Chars, Pos) of
    +    Chars = io:get_chars("", 1024),
    +    case handle_input(Chars, Pos) of
             stop -> stop;
             NewPos ->
    -            io:put_chars(clear_selection(Pos)),
    -            loop(NewPos)
    +            io:put_chars(clear_selection(Pos)),
    +            loop(NewPos)
         end.
     
    -handle_input("\e[A" ++ Rest, Pos) ->
    +handle_input("\e[A" ++ Rest, Pos) ->
         %% Up key
    -    handle_input(Rest, max(0, Pos - 3));
    -handle_input("\e[B" ++ Rest, Pos) ->
    +    handle_input(Rest, max(0, Pos - 3));
    +handle_input("\e[B" ++ Rest, Pos) ->
         %% Down key
    -    handle_input(Rest, min(8, Pos + 3));
    -handle_input("\e[C" ++ Rest, Pos) ->
    +    handle_input(Rest, min(8, Pos + 3));
    +handle_input("\e[C" ++ Rest, Pos) ->
         %% right key
    -    handle_input(Rest, min(8, Pos + 1));
    -handle_input("\e[D" ++ Rest, Pos) ->
    +    handle_input(Rest, min(8, Pos + 1));
    +handle_input("\e[D" ++ Rest, Pos) ->
         %% left key
    -    handle_input(Rest, max(0, Pos - 1));
    -handle_input("q" ++ _, _State) ->
    +    handle_input(Rest, max(0, Pos - 1));
    +handle_input("q" ++ _, _State) ->
         stop;
    -handle_input([_ | T], State) ->
    -    handle_input(T, State);
    -handle_input([], State) ->
    +handle_input([_ | T], State) ->
    +    handle_input(T, State);
    +handle_input([], State) ->
         State.

    Note that when using io:get_chars/2 with the shell set in {noshell, raw} mode it will return as soon as any data is available. The number of characters is the maximum number that will be returned. We use 1024 here to make sure that @@ -181,24 +181,24 @@ %% \b = Move cursor left %% \e[C = Move cursor right %% \n = Move cursor down -clear_selection(Pos) -> - [set_position(Pos), +clear_selection(Pos) -> + [set_position(Pos), " ","\b\b\b\b\b\b\b\n", " \e[C\e[C\e[C\e[C\e[C ", - "\b\b\b\b\b\b\b\n"," "]. + "\b\b\b\b\b\b\b\n"," "]. -draw_selection(Pos) -> - [set_position(Pos), +draw_selection(Pos) -> + [set_position(Pos), "┌─────┐","\b\b\b\b\b\b\b\n", "│\e[C\e[C\e[C\e[C\e[C│", - "\b\b\b\b\b\b\b\n","└─────┘"]. + "\b\b\b\b\b\b\b\n","└─────┘"]. %% Set the cursor position to be at the top %% left of the field of the given position -set_position(Pos) -> - Row = 6 + (Pos div 3) * 4, - Col = 7 + (Pos rem 3) * 8, - io_lib:format("\e[~p;~pH",[Row, Col]).

    Now we have a program where we can move the marker around the board. +set_position(Pos) -> + Row = 6 + (Pos div 3) * 4, + Col = 7 + (Pos rem 3) * 8, + io_lib:format("\e[~p;~pH",[Row, Col]).

    Now we have a program where we can move the marker around the board. To complete the game we need to add some state so that we know which squares are marked and whos turn it is. You can find the final solution in tic-tac-toe.es.

    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/timer.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1427)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/timer.html 2026-08-21 04:00:31.306372114 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/timer.html 2026-08-21 04:00:31.307372121 +0000 @@ -105,15 +105,15 @@ the Timer Module section in the Efficiency Guide.

    For more information on timers in Erlang in general, see the Timers section of the Time and Time Correction in Erlang -ERTS User's guide.

    Examples

    Example 1

    The following example shows how to print "Hello World!" in 5 seconds:

    1> timer:apply_after(5000, io, format, ["~nHello World!~n", []]).
    -{ok,TRef}
    +ERTS User's guide.

    Examples

    Example 1

    The following example shows how to print "Hello World!" in 5 seconds:

    1> timer:apply_after(5000, io, format, ["~nHello World!~n", []]).
    +{ok,TRef}
     Hello World!

    Example 2

    The following example shows a process performing a certain action, and if this -action is not completed within a certain limit, the process is killed:

    Pid = spawn(mod, fun, [foo, bar]),
    +action is not completed within a certain limit, the process is killed:

    Pid = spawn(mod, fun, [foo, bar]),
     %% If pid is not finished in 10 seconds, kill him
    -{ok, R} = timer:kill_after(timer:seconds(10), Pid),
    +{ok, R} = timer:kill_after(timer:seconds(10), Pid),
     ...
     %% We change our mind...
    -timer:cancel(R),
    +timer:cancel(R),
     ...

    Notes

    A timer can always be removed by calling cancel/1.

    An interval timer, that is, a timer created by evaluating any of the functions apply_interval/2, apply_interval/3, apply_interval/4, apply_repeatedly/2, apply_repeatedly/3, apply_repeatedly/4, @@ -134,20 +134,20 @@ process which set the timer about its completion, by sending it a done message.

    Using self/0 inside the timed function, the code below does not work as intended. The task gets done, but the done message gets sent to the wrong -process and is lost.

    1> timer:apply_after(1000, fun() -> do_something(), self() ! done end).
    -{ok,TRef}
    +process and is lost.

    1> timer:apply_after(1000, fun() -> do_something(), self() ! done end).
    +{ok,TRef}
     2> receive done -> done after 5000 -> timeout end.
     %% ... 5s pass...
     timeout

    The code below calls self/0 in the process which sets the timer and assigns it to a variable, which is then used in the function to send the done message to, -and so works as intended.

    1> Target = self()
    +and so works as intended.

    1> Target = self()
     <0.82.0>
    -2> timer:apply_after(1000, fun() -> do_something(), Target ! done end).
    -{ok,TRef}
    +2> timer:apply_after(1000, fun() -> do_something(), Target ! done end).
    +{ok,TRef}
     3> receive done -> done after 5000 -> timeout end.
     %% ... 1s passes...
    -done

    Another option is to pass the message target as a parameter to the function.

    1> timer:apply_after(1000, fun(Target) -> do_something(), Target ! done end, [self()]).
    -{ok,TRef}
    +done

    Another option is to pass the message target as a parameter to the function.

    1> timer:apply_after(1000, fun(Target) -> do_something(), Target ! done end, [self()]).
    +{ok,TRef}
     2> receive done -> done after 5000 -> timeout end.
     %% ... 1s passes...
     done
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/unicode.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1586)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/unicode.html 2026-08-21 04:00:31.333372290 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/unicode.html 2026-08-21 04:00:31.333372290 +0000 @@ -1036,13 +1036,13 @@ the first part of a (so far) valid UTF character.

    If one UTF character is split over two consecutive binaries in the Data, the conversion succeeds. This means that a character can be decoded from a range of binaries as long as the whole range is specified as input without errors -occurring.

    Example:

    decode_data(Data) ->
    -   case unicode:characters_to_list(Data,unicode) of
    -      {incomplete,Encoded, Rest} ->
    -            More = get_some_more_data(),
    -            Encoded ++ decode_data([Rest, More]);
    -      {error,Encoded,Rest} ->
    -            handle_error(Encoded,Rest);
    +occurring.

    Example:

    decode_data(Data) ->
    +   case unicode:characters_to_list(Data,unicode) of
    +      {incomplete,Encoded, Rest} ->
    +            More = get_some_more_data(),
    +            Encoded ++ decode_data([Rest, More]);
    +      {error,Encoded,Rest} ->
    +            handle_error(Encoded,Rest);
           List ->
                 List
        end.

    However, bit strings that are not whole bytes are not allowed, so a UTF @@ -1077,8 +1077,8 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form -of canonical equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    4> unicode:characters_to_nfc_binary([<<"abc..a">>,[778],$a,[776],$o,[776]]).
    -<<"abc..åäö"/utf8>>
    +of canonical equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    4> unicode:characters_to_nfc_binary([<<"abc..a">>,[778],$a,[776],$o,[776]]).
    +<<"abc..åäö"/utf8>>
    @@ -1109,7 +1109,7 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form -of canonical equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    3> unicode:characters_to_nfc_list([<<"abc..a">>,[778],$a,[776],$o,[776]]).
    +of canonical equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    3> unicode:characters_to_nfc_list([<<"abc..a">>,[778],$a,[776],$o,[776]]).
     "abc..åäö"
    @@ -1141,8 +1141,8 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form -of canonical equivalent Decomposed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    2> unicode:characters_to_nfd_binary("abc..åäö").
    -<<97,98,99,46,46,97,204,138,97,204,136,111,204,136>>
    +of canonical equivalent Decomposed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    2> unicode:characters_to_nfd_binary("abc..åäö").
    +<<97,98,99,46,46,97,204,138,97,204,136,111,204,136>>
    @@ -1173,8 +1173,8 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form -of canonical equivalent Decomposed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    1> unicode:characters_to_nfd_list("abc..åäö").
    -[97,98,99,46,46,97,778,97,776,111,776]
    +of canonical equivalent Decomposed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    1> unicode:characters_to_nfd_list("abc..åäö").
    +[97,98,99,46,46,97,778,97,776,111,776]
    @@ -1205,8 +1205,8 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form -of compatibly equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    4> unicode:characters_to_nfkc_binary([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]).
    -<<"abc..åäö32"/utf8>>
    +of compatibly equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    4> unicode:characters_to_nfkc_binary([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]).
    +<<"abc..åäö32"/utf8>>
    @@ -1237,7 +1237,7 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form -of compatibly equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    3> unicode:characters_to_nfkc_list([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]).
    +of compatibly equivalent Composed characters according to the Unicode standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    3> unicode:characters_to_nfkc_list([<<"abc..a">>,[778],$a,[776],$o,[776],[65299,65298]]).
     "abc..åäö32"
    @@ -1270,8 +1270,8 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form of compatibly equivalent Decomposed characters according to the Unicode -standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    2> unicode:characters_to_nfkd_binary(["abc..åäö",[65299,65298]]).
    -<<97,98,99,46,46,97,204,138,97,204,136,111,204,136,51,50>>
    +standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is an utf8 encoded binary.

    2> unicode:characters_to_nfkd_binary(["abc..åäö",[65299,65298]]).
    +<<97,98,99,46,46,97,204,138,97,204,136,111,204,136,51,50>>
    @@ -1303,8 +1303,8 @@

    Converts a possibly deep list of characters and binaries into a Normalized Form of compatibly equivalent Decomposed characters according to the Unicode -standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    1> unicode:characters_to_nfkd_list(["abc..åäö",[65299,65298]]).
    -[97,98,99,46,46,97,778,97,776,111,776,51,50]
    +standard.

    Any binaries in the input must be encoded with utf8 encoding.

    The result is a list of characters.

    1> unicode:characters_to_nfkd_list(["abc..åäö",[65299,65298]]).
    +[97,98,99,46,46,97,778,97,776,111,776,51,50]
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/unicode_usage.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1740)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/unicode_usage.html 2026-08-21 04:00:31.369372524 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/unicode_usage.html 2026-08-21 04:00:31.369372524 +0000 @@ -263,20 +263,20 @@ iolists, where binaries and lists can be combined to represent a sequence of bytes. In the same way, the Unicode-aware modules often allow for combinations of binaries and lists, where the binaries have characters encoded in UTF-8 and -the lists contain such binaries or numbers representing Unicode code points:

    unicode_binary() = binary() with characters encoded in UTF-8 coding standard
    +the lists contain such binaries or numbers representing Unicode code points:

    unicode_binary() = binary() with characters encoded in UTF-8 coding standard
     
    -chardata() = charlist() | unicode_binary()
    +chardata() = charlist() | unicode_binary()
     
    -charlist() = maybe_improper_list(char() | unicode_binary() | charlist(),
    -  unicode_binary() | nil())

    The module unicode even supports similar mixes with binaries containing +charlist() = maybe_improper_list(char() | unicode_binary() | charlist(), + unicode_binary() | nil())

    The module unicode even supports similar mixes with binaries containing other encodings than UTF-8, but that is a special case to allow for conversions -to and from external data:

    external_unicode_binary() = binary() with characters coded in a user-specified
    -  Unicode encoding other than UTF-8 (UTF-16 or UTF-32)
    +to and from external data:

    external_unicode_binary() = binary() with characters coded in a user-specified
    +  Unicode encoding other than UTF-8 (UTF-16 or UTF-32)
     
    -external_chardata() = external_charlist() | external_unicode_binary()
    +external_chardata() = external_charlist() | external_unicode_binary()
     
    -external_charlist() = maybe_improper_list(char() | external_unicode_binary() |
    -  external_charlist(), external_unicode_binary() | nil())

    Basic Language Support

    As from Erlang/OTP R16, Erlang source files can be +external_charlist() = maybe_improper_list(char() | external_unicode_binary() | + external_charlist(), external_unicode_binary() | nil())

    Basic Language Support

    As from Erlang/OTP R16, Erlang source files can be written in UTF-8 or bytewise (latin1) encoding. For information about how to state the encoding of an Erlang source file, see the epp module. As from Erlang/OTP R16, strings and comments can be written using @@ -300,12 +300,12 @@ In the following example, the code point of a Cyrillic с is output:

    7> $с.
     1089

    Heuristic String Detection

    In certain output functions and in the output of return values in the shell, Erlang tries to detect string data in lists and binaries heuristically. -Typically you will see heuristic detection in a situation like this:

    1> [97,98,99].
    +Typically you will see heuristic detection in a situation like this:

    1> [97,98,99].
     "abc"
    -2> <<97,98,99>>.
    -<<"abc">>
    -3> <<195,165,195,164,195,182>>.
    -<<"åäö"/utf8>>

    Here the shell detects lists containing printable characters or binaries +2> <<97,98,99>>. +<<"abc">> +3> <<195,165,195,164,195,182>>. +<<"åäö"/utf8>>

    Here the shell detects lists containing printable characters or binaries containing printable characters in bytewise or UTF-8 encoding. But what is a printable character? One view is that anything the Unicode standard thinks is printable, is also printable according to the heuristic detection. The result is @@ -320,32 +320,32 @@ controls how heuristic string detection is done. More ranges are expected to be added in the future, enabling tailoring of the heuristics to the language and region relevant to the user.

    The following examples show the two startup options:

    $ erl +pc latin1
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> [1024].
    -[1024]
    -2> [1070,1085,1080,1082,1086,1076].
    -[1070,1085,1080,1082,1086,1076]
    -3> [229,228,246].
    +Eshell V5.10.1  (abort with ^G)
    +1> [1024].
    +[1024]
    +2> [1070,1085,1080,1082,1086,1076].
    +[1070,1085,1080,1082,1086,1076]
    +3> [229,228,246].
     "åäö"
    -4> <<208,174,208,189,208,184,208,186,208,190,208,180>>.
    -<<208,174,208,189,208,184,208,186,208,190,208,180>>
    -5> <<229/utf8,228/utf8,246/utf8>>.
    -<<"åäö"/utf8>>
    $ erl +pc unicode
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +4> <<208,174,208,189,208,184,208,186,208,190,208,180>>.
    +<<208,174,208,189,208,184,208,186,208,190,208,180>>
    +5> <<229/utf8,228/utf8,246/utf8>>.
    +<<"åäö"/utf8>>
    $ erl +pc unicode
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> [1024].
    +Eshell V5.10.1  (abort with ^G)
    +1> [1024].
     "Ѐ"
    -2> [1070,1085,1080,1082,1086,1076].
    +2> [1070,1085,1080,1082,1086,1076].
     "Юникод"
    -3> [229,228,246].
    +3> [229,228,246].
     "åäö"
    -4> <<208,174,208,189,208,184,208,186,208,190,208,180>>.
    -<<"Юникод"/utf8>>
    -5> <<229/utf8,228/utf8,246/utf8>>.
    -<<"åäö"/utf8>>

    In the examples, you can see that the default Erlang shell interprets only +4> <<208,174,208,189,208,184,208,186,208,190,208,180>>. +<<"Юникод"/utf8>> +5> <<229/utf8,228/utf8,246/utf8>>. +<<"åäö"/utf8>>

    In the examples, you can see that the default Erlang shell interprets only characters from the ISO Latin1 range as printable and only detects lists or binaries with those "printable" characters as containing string data. The valid UTF-8 binary containing the Russian word "Юникод", is not printed as a string. @@ -353,17 +353,17 @@ outputs anything containing printable Unicode data (in binaries, either UTF-8 or bytewise encoded) as string data.

    These heuristics are also used by io:format/2, io_lib:format/2, and friends when modifier t is used with ~p or ~P:

    $ erl +pc latin1
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> io:format("~tp~n",[{<<"åäö">>, <<"åäö"/utf8>>, <<208,174,208,189,208,184,208,186,208,190,208,180>>}]).
    -{<<"åäö">>,<<"åäö"/utf8>>,<<208,174,208,189,208,184,208,186,208,190,208,180>>}
    +Eshell V5.10.1  (abort with ^G)
    +1> io:format("~tp~n",[{<<"åäö">>, <<"åäö"/utf8>>, <<208,174,208,189,208,184,208,186,208,190,208,180>>}]).
    +{<<"åäö">>,<<"åäö"/utf8>>,<<208,174,208,189,208,184,208,186,208,190,208,180>>}
     ok
    $ erl +pc unicode
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> io:format("~tp~n",[{<<"åäö">>, <<"åäö"/utf8>>, <<208,174,208,189,208,184,208,186,208,190,208,180>>}]).
    -{<<"åäö">>,<<"åäö"/utf8>>,<<"Юникод"/utf8>>}
    +Eshell V5.10.1  (abort with ^G)
    +1> io:format("~tp~n",[{<<"åäö">>, <<"åäö"/utf8>>, <<208,174,208,189,208,184,208,186,208,190,208,180>>}]).
    +{<<"åäö">>,<<"åäö"/utf8>>,<<"Юникод"/utf8>>}
     ok

    Notice that this only affects heuristic interpretation of lists and binaries on output. For example, the ~ts format sequence always outputs a valid list of characters, regardless of the +pc setting, as the programmer has explicitly @@ -380,19 +380,19 @@ capable of. There is no portable way for Erlang to ask the terminal about its UTF-8 capacity, we have to rely on the language and character type settings.

    To investigate what Erlang thinks about the terminal, the call io:getopts() can be used when the shell is started:

    $ LC_CTYPE=en_US.ISO-8859-1 erl
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> lists:keyfind(encoding, 1, io:getopts()).
    -{encoding,latin1}
    -2> q().
    +Eshell V5.10.1  (abort with ^G)
    +1> lists:keyfind(encoding, 1, io:getopts()).
    +{encoding,latin1}
    +2> q().
     ok
     $ LC_CTYPE=en_US.UTF-8 erl
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> lists:keyfind(encoding, 1, io:getopts()).
    -{encoding,unicode}
    +Eshell V5.10.1  (abort with ^G)
    +1> lists:keyfind(encoding, 1, io:getopts()).
    +{encoding,unicode}
     2>

    When (finally?) everything is in order with the locale settings, fonts. and the terminal emulator, you have probably found a way to input characters in the script you desire. For testing, the simplest way is to add some keyboard @@ -405,14 +405,14 @@ easily if you are not used to this. For example, entering commands using a Cyrillic character set is not easily done in the Erlang shell.

    Now you are set up for some Unicode input and output. The simplest thing to do is to enter a string in the shell:

    $ erl
    -Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source] [async-threads:0] [hipe] [kernel-poll:false]
     
    -Eshell V5.10.1  (abort with ^G)
    -1> lists:keyfind(encoding, 1, io:getopts()).
    -{encoding,unicode}
    +Eshell V5.10.1  (abort with ^G)
    +1> lists:keyfind(encoding, 1, io:getopts()).
    +{encoding,unicode}
     2> "Юникод".
     "Юникод"
    -3> io:format("~ts~n", [v(2)]).
    +3> io:format("~ts~n", [v(2)]).
     Юникод
     ok
     4>

    While strings can be input as Unicode characters, the language elements are @@ -439,10 +439,10 @@ charlist() represented by it.

    #!/usr/bin/env escript
     %%! -kernel standard_io_encoding latin1
     
    -main(_) ->
    -  {ok, Char} = file:read_line(standard_io),
    -  ok = file:write(standard_io, string:trim(Char)),
    -  ok = file:write(standard_io, io_lib:format(": ~w~n",[string:trim(Char)])),
    +main(_) ->
    +  {ok, Char} = file:read_line(standard_io),
    +  ok = file:write(standard_io, string:trim(Char)),
    +  ok = file:write(standard_io, io_lib:format(": ~w~n",[string:trim(Char)])),
       ok.
    $ escript test.es
     ξ
     ξ: [206,190]

    ξ would normally be represented as the integer 958, but since we are using @@ -642,13 +642,13 @@ example {encoding,utf8}).

    Functions reading Erlang syntax from files recognize the coding: comment and can therefore handle Unicode data on input. When writing Erlang terms to a file, you are advised to insert such comments when applicable:

    $ erl +fna +pc unicode
    -Erlang R16B (erts-5.10.1) [source]  [async-threads:0] [hipe] [kernel-poll:false]
    +Erlang R16B (erts-5.10.1) [source]  [async-threads:0] [hipe] [kernel-poll:false]
     
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/uri_string.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1056))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/uri_string.html	2026-08-21 04:00:31.398372713 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/uri_string.html	2026-08-21 04:00:31.399372720 +0000
    @@ -551,11 +551,11 @@
     

    Composes a form-urlencoded QueryString based on a QueryList, a list of non-percent-encoded key-value pairs.

    Form-urlencoding is defined in section 4.10.21.6 of the HTML 5.2 specification and in section 4.10.22.6 of the HTML 5.0 -specification for non-UTF-8 encodings.

    See also the opposite operation dissect_query/1.

    Example:

    1> uri_string:compose_query([{"foo bar","1"},{"city","örebro"}]).
    +specification for non-UTF-8 encodings.

    See also the opposite operation dissect_query/1.

    Example:

    1> uri_string:compose_query([{"foo bar","1"},{"city","örebro"}]).
     "foo+bar=1&city=%C3%B6rebro"
    -2> uri_string:compose_query([{<<"foo bar">>,<<"1">>},
    -2> {<<"city">>,<<"örebro"/utf8>>}]).
    -<<"foo+bar=1&city=%C3%B6rebro">>
    +2>
    uri_string:compose_query([{<<"foo bar">>,<<"1">>}, +2> {<<"city">>,<<"örebro"/utf8>>}]). +<<"foo+bar=1&city=%C3%B6rebro">>
    @@ -598,12 +598,12 @@ ";" (U+003B) character.

    Bytes that are out of the range 0x2A, 0x2D, 0x2E, 0x30 to 0x39, 0x41 to 0x5A, 0x5F, 0x61 to 0x7A, are percent-encoded (U+0025 PERCENT SIGN character (%) followed by uppercase ASCII hex digits representing the hexadecimal value of the -byte).

    See also the opposite operation dissect_query/1.

    Example:

    1> uri_string:compose_query([{"foo bar","1"},{"city","örebro"}],
    -1> [{encoding, latin1}]).
    +byte).

    See also the opposite operation dissect_query/1.

    Example:

    1> uri_string:compose_query([{"foo bar","1"},{"city","örebro"}],
    +1> [{encoding, latin1}]).
     "foo+bar=1&city=%F6rebro"
    -2> uri_string:compose_query([{<<"foo bar">>,<<"1">>},
    -2> {<<"city">>,<<"東京"/utf8>>}], [{encoding, latin1}]).
    -<<"foo+bar=1&city=%26%2326481%3B%26%2320140%3B">>
    +2>
    uri_string:compose_query([{<<"foo bar">>,<<"1">>}, +2> {<<"city">>,<<"東京"/utf8>>}], [{encoding, latin1}]). +<<"foo+bar=1&city=%26%2326481%3B%26%2320140%3B">>
    @@ -639,11 +639,11 @@

    Dissects an urlencoded QueryString and returns a QueryList, a list of non-percent-encoded key-value pairs.

    Form-urlencoding is defined in section 4.10.21.6 of the HTML 5.2 specification and in section 4.10.22.6 of the HTML 5.0 -specification for non-UTF-8 encodings.

    See also the opposite operation compose_query/1.

    Example:

    1> uri_string:dissect_query("foo+bar=1&city=%C3%B6rebro").
    -[{"foo bar","1"},{"city","örebro"}]
    -2> uri_string:dissect_query(<<"foo+bar=1&city=%26%2326481%3B%26%2320140%3B">>).
    -[{<<"foo bar">>,<<"1">>},
    - {<<"city">>,<<230,157,177,228,186,172>>}]
    +specification for non-UTF-8 encodings.

    See also the opposite operation compose_query/1.

    Example:

    1> uri_string:dissect_query("foo+bar=1&city=%C3%B6rebro").
    +[{"foo bar","1"},{"city","örebro"}]
    +2> uri_string:dissect_query(<<"foo+bar=1&city=%26%2326481%3B%26%2320140%3B">>).
    +[{<<"foo bar">>,<<"1">>},
    + {<<"city">>,<<230,157,177,228,186,172>>}]
    @@ -677,14 +677,14 @@

    Transforms an URI into a normalized form using Syntax-Based Normalization as defined by RFC 3986.

    This function implements case normalization, percent-encoding normalization, path segment normalization and scheme based normalization for HTTP(S) with basic -support for FTP, SSH, SFTP and TFTP.

    Example:

    1> uri_string:normalize("/a/b/c/./../../g").
    +support for FTP, SSH, SFTP and TFTP.

    Example:

    1> uri_string:normalize("/a/b/c/./../../g").
     "/a/g"
    -2> uri_string:normalize(<<"mid/content=5/../6">>).
    -<<"mid/6">>
    -3> uri_string:normalize("http://localhost:80").
    +2> uri_string:normalize(<<"mid/content=5/../6">>).
    +<<"mid/6">>
    +3> uri_string:normalize("http://localhost:80").
     "http://localhost/"
    -4> uri_string:normalize(#href_anchor"ss">scheme => "http",port => 80,path => "/a/b/c/./../../g",
    -4> host => "localhost-örebro"}).
    +4> uri_string:normalize(#href_anchor"ss">scheme => "http",port => 80,path => "/a/b/c/./../../g",
    +4> host => "localhost-örebro"}).
     "http://localhost-%C3%B6rebro/a/g"
    @@ -721,15 +721,15 @@

    Same as normalize/1 but with an additional Options parameter, that controls whether the normalized URI shall be returned as an -uri_map().

    There is one supported option: return_map.

    Example:

    1> uri_string:normalize("/a/b/c/./../../g", [return_map]).
    -#{path => "/a/g"}
    -2> uri_string:normalize(<<"mid/content=5/../6">>, [return_map]).
    -#{path => <<"mid/6">>}
    -3> uri_string:normalize("http://localhost:80", [return_map]).
    -#{scheme => "http",path => "/",host => "localhost"}
    -4> uri_string:normalize(#{scheme => "http",port => 80,path => "/a/b/c/./../../g",
    -4> host => "localhost-örebro"}, [return_map]).
    -#{scheme => "http",path => "/a/g",host => "localhost-örebro"}
    +uri_map().

    There is one supported option: return_map.

    Example:

    1> uri_string:normalize("/a/b/c/./../../g", [return_map]).
    +#{path => "/a/g"}
    +2> uri_string:normalize(<<"mid/content=5/../6">>, [return_map]).
    +#{path => <<"mid/6">>}
    +3> uri_string:normalize("http://localhost:80", [return_map]).
    +#{scheme => "http",path => "/",host => "localhost"}
    +4> uri_string:normalize(#{scheme => "http",port => 80,path => "/a/b/c/./../../g",
    +4> host => "localhost-örebro"}, [return_map]).
    +#{scheme => "http",path => "/a/g",host => "localhost-örebro"}
    @@ -761,14 +761,14 @@

    Parses an RFC 3986 compliant uri_string/0 into a uri_map/0, that holds the parsed components of the -URI. If parsing fails, an error tuple is returned.

    See also the opposite operation recompose/1.

    Example:

    1> uri_string:parse("foo://user@example.com:8042/over/there?name=ferret#nose").
    -#{fragment => "nose",host => "example.com",
    +URI. If parsing fails, an error tuple is returned.

    See also the opposite operation recompose/1.

    Example:

    1> uri_string:parse("foo://user@example.com:8042/over/there?name=ferret#nose").
    +#{fragment => "nose",host => "example.com",
       path => "/over/there",port => 8042,query => "name=ferret",
    -  scheme => foo,userinfo => "user"}
    -2> uri_string:parse(<<"foo://user@example.com:8042/over/there?name=ferret">>).
    -#{host => <<"example.com">>,path => <<"/over/there">>,
    -  port => 8042,query => <<"name=ferret">>,scheme => <<"foo">>,
    -  userinfo => <<"user">>}
    +
    scheme => foo,userinfo => "user"} +2> uri_string:parse(<<"foo://user@example.com:8042/over/there?name=ferret">>). +#{host => <<"example.com">>,path => <<"/over/there">>, + port => 8042,query => <<"name=ferret">>,scheme => <<"foo">>, + userinfo => <<"user">>}
    @@ -808,16 +808,16 @@

    Decodes all percent-encoded triplets in the input that can be both a uri_string/0 and a uri_map/0.

    Note, that this function performs raw decoding and it shall be used on already parsed URI components. Applying this function directly on a standard URI can -effectively change it.

    If the input encoding is not UTF-8, an error tuple is returned.

    Example:

    1> uri_string:percent_decode(#{host => "localhost-%C3%B6rebro",path => [],
    -1> scheme => "http"}).
    -#{host => "localhost-örebro",path => [],scheme => "http"}
    -2> uri_string:percent_decode(<<"%C3%B6rebro">>).
    -<<"örebro"/utf8>>

    Warning

    Using uri_string:percent_decode/1 directly on a URI is not safe. This +effectively change it.

    If the input encoding is not UTF-8, an error tuple is returned.

    Example:

    1> uri_string:percent_decode(#{host => "localhost-%C3%B6rebro",path => [],
    +1> scheme => "http"}).
    +#{host => "localhost-örebro",path => [],scheme => "http"}
    +2> uri_string:percent_decode(<<"%C3%B6rebro">>).
    +<<"örebro"/utf8>>

    Warning

    Using uri_string:percent_decode/1 directly on a URI is not safe. This example shows, that after each consecutive application of the function the -resulting URI will be changed. None of these URIs refer to the same resource.

    3> uri_string:percent_decode(<<"http://local%252Fhost/path">>).
    -<<"http://local%2Fhost/path">>
    -4> uri_string:percent_decode(<<"http://local%2Fhost/path">>).
    -<<"http://local/host/path">>
    +resulting URI will be changed. None of these URIs refer to the same resource.

    3> uri_string:percent_decode(<<"http://local%252Fhost/path">>).
    +<<"http://local%2Fhost/path">>
    +4> uri_string:percent_decode(<<"http://local%2Fhost/path">>).
    +<<"http://local/host/path">>
    @@ -849,10 +849,10 @@

    Replaces characters out of unreserved set with their percent encoded equivalents.

    Unreserved characters defined in -RFC 3986 are not quoted.

    Example:

    1> uri_string:quote("SomeId/04").
    +RFC 3986 are not quoted.

    Example:

    1> uri_string:quote("SomeId/04").
     "SomeId%2F04"
    -2> uri_string:quote(<<"SomeId/04">>).
    -<<"SomeId%2F04">>

    Warning

    Function is not aware about any URI component context and should not be used +2> uri_string:quote(<<"SomeId/04">>). +<<"SomeId%2F04">>

    Warning

    Function is not aware about any URI component context and should not be used on whole URI. If applied more than once on the same data, might produce unexpected results.

    @@ -886,10 +886,10 @@

    Same as quote/1, but Safe allows user to provide a list of -characters to be protected from encoding.

    Example:

    1> uri_string:quote("SomeId/04", "/").
    +characters to be protected from encoding.

    Example:

    1> uri_string:quote("SomeId/04", "/").
     "SomeId/04"
    -2> uri_string:quote(<<"SomeId/04">>, "/").
    -<<"SomeId/04">>

    Warning

    Function is not aware about any URI component context and should not be used +2> uri_string:quote(<<"SomeId/04">>, "/"). +<<"SomeId/04">>

    Warning

    Function is not aware about any URI component context and should not be used on whole URI. If applied more than once on the same data, might produce unexpected results.

    @@ -923,13 +923,13 @@

    Creates an RFC 3986 compliant URIString (percent-encoded), based on the components of URIMap. If the -URIMap is invalid, an error tuple is returned.

    See also the opposite operation parse/1.

    Example:

    1> URIMap = #{fragment => "nose", host => "example.com", path => "/over/there",
    -1> port => 8042, query => "name=ferret", scheme => "foo", userinfo => "user"}.
    -#{fragment => "nose",host => "example.com",
    +URIMap is invalid, an error tuple is returned.

    See also the opposite operation parse/1.

    Example:

    1> URIMap = #{fragment => "nose", host => "example.com", path => "/over/there",
    +1> port => 8042, query => "name=ferret", scheme => "foo", userinfo => "user"}.
    +#{fragment => "nose",host => "example.com",
       path => "/over/there",port => 8042,query => "name=ferret",
    -  scheme => "foo",userinfo => "user"}
    +  scheme => "foo",userinfo => "user"}
     
    -2> uri_string:recompose(URIMap).
    +2> uri_string:recompose(URIMap).
     "foo://example.com:8042/over/there?name=ferret#nose"
    @@ -966,13 +966,13 @@

    Convert a RefURI reference that might be relative to a given base URI into the parsed components of the reference's target, which can then be recomposed to -form the target URI.

    Example:

    1> uri_string:resolve("/abs/ol/ute", "http://localhost/a/b/c?q").
    +form the target URI.

    Example:

    1> uri_string:resolve("/abs/ol/ute", "http://localhost/a/b/c?q").
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/uri_string_usage.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1070))
    --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/uri_string_usage.html	2026-08-21 04:00:31.424372882 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/uri_string_usage.html	2026-08-21 04:00:31.424372882 +0000
    @@ -126,19 +126,19 @@
     to explain this by an example.

    Let's say that we would like to create the following URI and send it over the network: http://cities/örebro?foo bar. This is not a valid URI as it contains characters that are not allowed in a URI such as "ö" and the space. We can -verify this by parsing the URI:

      1> uri_string:parse("http://cities/örebro?foo bar").
    -  {error,invalid_uri,":"}

    The URI parser tries all possible combinations to interpret the input and fails +verify this by parsing the URI:

      1> uri_string:parse("http://cities/örebro?foo bar").
    +  {error,invalid_uri,":"}

    The URI parser tries all possible combinations to interpret the input and fails at the last attempt when it encounters the colon character ":". Note, that the inital fault occurs when the parser attempts to interpret the character "ö" and after a failure back-tracks to the point where it has another possible parsing alternative.

    The proper way to solve this problem is to use uri_string:recompose/1 with a -uri_map() as input:

      2> uri_string:recompose(#{scheme => "http", host => "cities", path => "/örebro",
    -  query => "foo bar"}).
    +uri_map() as input:

      2> uri_string:recompose(#{scheme => "http", host => "cities", path => "/örebro",
    +  query => "foo bar"}).
       "http://cities/%C3%B6rebro?foo%20bar"

    The result is a valid URI where all the special characters are encoded as defined by the standard. Applying uri_string:parse/1 and -uri_string:percent_decode/1 on the URI returns the original input:

      3> uri_string:percent_decode(uri_string:parse("http://cities/%C3%B6rebro?foo%20bar")).
    -  #{host => "cities",path => "/örebro",query => "foo bar",
    -  scheme => "http"}

    This symmetric property is heavily used in our property test suite.

    Percent-encoding

    As you have seen in the previous chapter, a standard URI can only contain a +uri_string:percent_decode/1 on the URI returns the original input:

      3> uri_string:percent_decode(uri_string:parse("http://cities/%C3%B6rebro?foo%20bar")).
    +  #{host => "cities",path => "/örebro",query => "foo bar",
    +  scheme => "http"}

    This symmetric property is heavily used in our property test suite.

    Percent-encoding

    As you have seen in the previous chapter, a standard URI can only contain a strict subset of the US ASCII character set, moreover the allowed set of characters is not the same in the different URI components. Percent-encoding is a mechanism to represent a data octet in a component when that octet's @@ -155,27 +155,27 @@ question the library provides a utility function, uri_string:allowed_characters/0, that lists the allowed set of characters in each major URI component, and also in the -most important standard character sets.

        1> uri_string:allowed_characters().
    -    [{scheme,
    -     "+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"},
    -    {userinfo,
    -     "!$%&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    -    {host,
    -     "!$&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    -    {ipv4,".0123456789"},
    -    {ipv6,".0123456789:ABCDEFabcdef"},
    -    {regname,
    -     "!$%&'()*+,-.0123456789;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    -    {path,
    -     "!$%&'()*+,-./0123456789:;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    -    {query,
    -     "!$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    -    {fragment,
    -     "!$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    -    {reserved,"!#$&'()*+,/:;=?@[]"},
    -    {unreserved,
    -     "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"}]

    If a URI component has a character that is not allowed, it will be -percent-encoded when the URI is produced:

        2> uri_string:recompose(#{scheme => "https", host => "local#host", path => ""}).
    +most important standard character sets.

        1> uri_string:allowed_characters().
    +    [{scheme,
    +     "+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"},
    +    {userinfo,
    +     "!$%&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    +    {host,
    +     "!$&'()*+,-.0123456789:;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    +    {ipv4,".0123456789"},
    +    {ipv6,".0123456789:ABCDEFabcdef"},
    +    {regname,
    +     "!$%&'()*+,-.0123456789;=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    +    {path,
    +     "!$%&'()*+,-./0123456789:;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    +    {query,
    +     "!$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    +    {fragment,
    +     "!$%&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"},
    +    {reserved,"!#$&'()*+,/:;=?@[]"},
    +    {unreserved,
    +     "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"}]

    If a URI component has a character that is not allowed, it will be +percent-encoded when the URI is produced:

        2> uri_string:recompose(#{scheme => "https", host => "local#host", path => ""}).
         "https://local%23host"

    Consuming a URI containing percent-encoded triplets can take many steps. The following example shows how to handle an input URI that is not normalized and contains multiple percent-encoded triplets. First, the input @@ -187,32 +187,32 @@ You can try to normalize the input with uri_string:normalize/1. The normalize operation decodes those percent-encoded triplets that correspond to a character in the unreserved set. Normalization is a safe, idempotent operation that -converts a URI into its canonical form:

        4> uri_string:normalize("http://%6C%6Fcal%23host/%F6re%26bro%20").
    +converts a URI into its canonical form:

        4> uri_string:normalize("http://%6C%6Fcal%23host/%F6re%26bro%20").
         "http://local%23host/%F6re%26bro%20"
    -    5> uri_string:normalize("http://%6C%6Fcal%23host/%F6re%26bro%20", [return_map]).
    -    #{host => "local%23host",path => "/%F6re%26bro%20",
    -      scheme => "http"}

    There are still a few percent-encoded triplets left in the output. At this + 5> uri_string:normalize("http://%6C%6Fcal%23host/%F6re%26bro%20", [return_map]). + #{host => "local%23host",path => "/%F6re%26bro%20", + scheme => "http"}

    There are still a few percent-encoded triplets left in the output. At this point, when the URI is already parsed, it is safe to apply application specific decoding on the remaining character triplets. Erlang/OTP provides a function, uri_string:percent_decode/1 for raw percent decoding that you can use on the -host and path components, or on the whole map:

        6> uri_string:percent_decode("local%23host").
    +host and path components, or on the whole map:

        6> uri_string:percent_decode("local%23host").
         "local#host"
    -    7> uri_string:percent_decode("/%F6re%26bro%20").
    -    {error,invalid_utf8,<<"/öre&bro ">>}
    -    8> uri_string:percent_decode(#{host => "local%23host",path => "/%F6re%26bro%20",
    -    scheme => "http"}).
    -    {error,{invalid,{path,{invalid_utf8,<<"/öre&bro ">>}}}}

    The host was successfully decoded but the path contains at least one character + 7> uri_string:percent_decode("/%F6re%26bro%20"). + {error,invalid_utf8,<<"/öre&bro ">>} + 8> uri_string:percent_decode(#{host => "local%23host",path => "/%F6re%26bro%20", + scheme => "http"}). + {error,{invalid,{path,{invalid_utf8,<<"/öre&bro ">>}}}}

    The host was successfully decoded but the path contains at least one character with non-UTF-8 encoding. In order to be able to decode this, you have to make assumptions about the encoding used in these triplets. The most obvious choice is latin-1, so you can try uri_string:transcode/2, to transcode the path to -UTF-8 and run the percent-decode operation on the transcoded string:

        9> uri_string:transcode("/%F6re%26bro%20", [{in_encoding, latin1}]).
    +UTF-8 and run the percent-decode operation on the transcoded string:

        9> uri_string:transcode("/%F6re%26bro%20", [{in_encoding, latin1}]).
         "/%C3%B6re%26bro%20"
    -    10> uri_string:percent_decode("/%C3%B6re%26bro%20").
    +    10> uri_string:percent_decode("/%C3%B6re%26bro%20").
         "/öre&bro "

    It is important to emphasize that it is not safe to apply -uri_string:percent_decode/1 directly on an input URI:

        11> uri_string:percent_decode("http://%6C%6Fcal%23host/%C3%B6re%26bro%20").
    +uri_string:percent_decode/1 directly on an input URI:

        11> uri_string:percent_decode("http://%6C%6Fcal%23host/%C3%B6re%26bro%20").
         "http://local#host/öre&bro "
    -    12> uri_string:parse("http://local#host/öre&bro ").
    -    {error,invalid_uri,":"}

    Note

    Percent-encoding is implemented in uri_string:recompose/1 and it happens + 12> uri_string:parse("http://local#host/öre&bro "). + {error,invalid_uri,":"}

    Note

    Percent-encoding is implemented in uri_string:recompose/1 and it happens when converting a uri_map() into a uri_string(). Applying any percent-encoding directly on an input URI would not be safe just as in the case of /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/zip.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2139)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/zip.html 2026-08-21 04:00:31.457373097 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/zip.html 2026-08-21 04:00:31.456373091 +0000 @@ -772,29 +772,29 @@ archive. The iteration can be ended prematurely in a controlled manner by throwing an exception.

    Example:

    > Name = "dummy.zip".
     "dummy.zip"
    -> {ok, {Name, Bin}} = zip:create(Name, [{"foo", <<"FOO">>}, {"bar", <<"BAR">>}], [memory]).
    -{ok,{"dummy.zip",
    -     <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0,
    -       0,0,3,0,0,...>>}}
    -> {ok, FileSpec} = zip:foldl(fun(N, I, B, Acc) -> [{N, B(), I()} | Acc] end, [], {Name, Bin}).
    -{ok,[{"bar",<<"BAR">>,
    -      {file_info,3,regular,read_write,
    -                 {{2010,3,1},{19,2,10}},
    -                 {{2010,3,1},{19,2,10}},
    -                 {{2010,3,1},{19,2,10}},
    -                 54,1,0,0,0,0,0}},
    -     {"foo",<<"FOO">>,
    -      {file_info,3,regular,read_write,
    -                 {{2010,3,1},{19,2,10}},
    -                 {{2010,3,1},{19,2,10}},
    -                 {{2010,3,1},{19,2,10}},
    -                 54,1,0,0,0,0,0}}]}
    -> {ok, {Name, Bin}} = zip:create(Name, lists:reverse(FileSpec), [memory]).
    -{ok,{"dummy.zip",
    -     <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0,
    -       0,0,3,0,0,...>>}}
    -> catch zip:foldl(fun("foo", _, B, _) -> throw(B()); (_,_,_,Acc) -> Acc end, [], {Name, Bin}).
    -<<"FOO">>
    +> {ok, {Name, Bin}} = zip:create(Name, [{"foo", <<"FOO">>}, {"bar", <<"BAR">>}], [memory]). +{ok,{"dummy.zip", + <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0, + 0,0,3,0,0,...>>}} +> {ok, FileSpec} = zip:foldl(fun(N, I, B, Acc) -> [{N, B(), I()} | Acc] end, [], {Name, Bin}). +{ok,[{"bar",<<"BAR">>, + {file_info,3,regular,read_write, + {{2010,3,1},{19,2,10}}, + {{2010,3,1},{19,2,10}}, + {{2010,3,1},{19,2,10}}, + 54,1,0,0,0,0,0}}, + {"foo",<<"FOO">>, + {file_info,3,regular,read_write, + {{2010,3,1},{19,2,10}}, + {{2010,3,1},{19,2,10}}, + {{2010,3,1},{19,2,10}}, + 54,1,0,0,0,0,0}}]} +> {ok, {Name, Bin}} = zip:create(Name, lists:reverse(FileSpec), [memory]). +{ok,{"dummy.zip", + <<80,75,3,4,20,0,0,0,0,0,74,152,97,60,171,39,212,26,3,0, + 0,0,3,0,0,...>>}} +> catch zip:foldl(fun("foo", _, B, _) -> throw(B()); (_,_,_,Acc) -> Acc end, [], {Name, Bin}). +<<"FOO">>
    /usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/zstd.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1144)) --- old//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/zstd.html 2026-08-21 04:00:31.488373299 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/stdlib-7.3.0.1/doc/html/zstd.html 2026-08-21 04:00:31.488373299 +0000 @@ -96,25 +96,25 @@

    Zstandard compression interface.

    This module provides an API for the Zstandard library (www.zstd.net). It is used to compress and decompress data and offers the same compression ratio as zlib but at a lower CPU cost.

    Example:

    1> Data = ~"my data to be compressed".
    -2> Compressed = zstd:compress(Data).
    -3> zstd:decompress(Compressed).
    -[~"my data to be compressed"]

    If you are compressing or decompressing possibly large amounts of data, -it is also possible to do streamed compression/decompression.

    Example:

    1> Compress = fun F(Ctx, D) ->
    -                      case file:read(D, 5) of
    -                          {ok, Data} ->
    -                              {continue, C} = zstd:stream(Ctx, Data),
    -                              [C|F(Ctx, D)];
    +2> Compressed = zstd:compress(Data).
    +3> zstd:decompress(Compressed).
    +[~"my data to be compressed"]

    If you are compressing or decompressing possibly large amounts of data, +it is also possible to do streamed compression/decompression.

    Example:

    1> Compress = fun F(Ctx, D) ->
    +                      case file:read(D, 5) of
    +                          {ok, Data} ->
    +                              {continue, C} = zstd:stream(Ctx, Data),
    +                              [C|F(Ctx, D)];
                               eof ->
    -                              {done, C} = zstd:finish(Ctx, ""),
    +                              {done, C} = zstd:finish(Ctx, ""),
                                   C
                           end
                   end.
    -2> {ok, Ctx} = zstd:context(compress).
    -3> {ok, D} = file:open(File,[read,binary]).
    -4> Compressed = iolist_to_binary(Compress(Ctx, D)).
    -<<40,181,47,253,0,88,89,0,0,108,111,114,101,109,32,105,112,115,117,109>>
    -5> zstd:decompress(Compressed).
    -[~"lorem ipsum"]

    In all functions errors can be thrown, where Reason describes the error.

    Typical Reasons:

    • badarg - Bad argument.
    • zstd_error - An error generated by the Zstandard library.
    • not_on_controlling_process - The context was used by a process that +2> {ok, Ctx} = zstd:context(compress). +3> {ok, D} = file:open(File,[read,binary]). +4> Compressed = iolist_to_binary(Compress(Ctx, D)). +<<40,181,47,253,0,88,89,0,0,108,111,114,101,109,32,105,112,115,117,109>> +5> zstd:decompress(Compressed). +[~"lorem ipsum"]

    In all functions errors can be thrown, where Reason describes the error.

    Typical Reasons:

    • badarg - Bad argument.
    • zstd_error - An error generated by the Zstandard library.
    • not_on_controlling_process - The context was used by a process that did not create it.
    @@ -708,8 +708,8 @@ -

    Compress Data using the given compress_parameters/0 or the context/0.

    Example:

    1> zstd:compress("abc").
    -2> zstd:compress("abc", #{ compressionLevel => 20 }).
    +

    Compress Data using the given compress_parameters/0 or the context/0.

    Example:

    1> zstd:compress("abc").
    +2> zstd:compress("abc", #{ compressionLevel => 20 }).
    @@ -832,9 +832,9 @@ -

    Decompress Data using the given decompress_parameters/0 or the context/0.

    Example:

    1> Compressed = zstd:compress("abc").
    -2> zstd:decompress(Compressed).
    -[~"abc"]
    +

    Decompress Data using the given decompress_parameters/0 or the context/0.

    Example:

    1> Compressed = zstd:compress("abc").
    +2> zstd:decompress(Compressed).
    +[~"abc"]
    @@ -903,12 +903,12 @@ you can use get_dict_id/1 on the dictionary and compressed data, or just try to decompress as decompression will raise and exception if an incorrect dictionary is given.

    The compressionLevel set on a dictionary will override the compressionLevel -set in the context/0.

    Example:

    1> {ok, CDict} = zstd:dict(compress, Dict).
    -2> Data = lists:duplicate(100, 1).
    -[1, 1, 1 | _]
    -3> iolist_size(zstd:compress(Data)).
    +set in the context/0.

    Example:

    1> {ok, CDict} = zstd:dict(compress, Dict).
    +2> Data = lists:duplicate(100, 1).
    +[1, 1, 1 | _]
    +3> iolist_size(zstd:compress(Data)).
     17
    -4> iolist_size(zstd:compress(Data, #{ dictionary => CDict, dictIDFlag => false })).
    +4> iolist_size(zstd:compress(Data, #{ dictionary => CDict, dictIDFlag => false })).
     16

    As loading a dictionary can be a heavy operations, it is possible to create only a single dict/0 and provide it to multiple context/0.

    There is no API exposed in zstd to create a dictionary, instead use the zstd command line tool.

    @@ -942,11 +942,11 @@

    Finish compressing/decompressing data.

    This flushes all output buffers and resets the context/0 so -that it can be used for compressing/decompressing again.

    Example:

    1> {ok, DCtx} = zstd:context(decompress).
    -2> {continue, D1} = zstd:stream(DCtx, <<40,181,47,253,32>>).
    -3> {done, D2} = zstd:finish(DCtx, <<2,17,0,0,97,98>>).
    -4> iolist_to_binary([D1,D2]).
    -<<"ab">>
    +that it can be used for compressing/decompressing again.

    Example:

    1> {ok, DCtx} = zstd:context(decompress).
    +2> {continue, D1} = zstd:stream(DCtx, <<40,181,47,253,32>>).
    +3> {done, D2} = zstd:finish(DCtx, <<2,17,0,0,97,98>>).
    +4> iolist_to_binary([D1,D2]).
    +<<"ab">>
    @@ -976,10 +976,10 @@ -

    Get the dictionary ID of a dictionary or a frame.

    The dictionary ID 0 represents no dictionary.

    Example:

    1> {ok, CDict} = zstd:dict(compress, Dict).
    -2> zstd:get_dict_id(CDict).
    +

    Get the dictionary ID of a dictionary or a frame.

    The dictionary ID 0 represents no dictionary.

    Example:

    1> {ok, CDict} = zstd:dict(compress, Dict).
    +2> zstd:get_dict_id(CDict).
     1850243626
    -3> zstd:get_dict_id(zstd:compress("abc")).
    +3> zstd:get_dict_id(zstd:compress("abc")).
     0
    @@ -1021,11 +1021,11 @@

    Get header of a Zstandard compressed frame.

    A compressed Zstandard stream can consist of multiple frames. This function will read metadata from the first frame. This information -can be useful when debugging corrupted Zstandard streams.

    Example:

    1> Compressed = zstd:compress(~"abc").
    -2> zstd:get_frame_header(Compressed).
    -{ok,#{frameContentSize => 3,windowSize => 3,blockSizeMax => 3,
    +can be useful when debugging corrupted Zstandard streams.

    Example:

    1> Compressed = zstd:compress(~"abc").
    +2> zstd:get_frame_header(Compressed).
    +{ok,#{frameContentSize => 3,windowSize => 3,blockSizeMax => 3,
           frameType => 'ZSTD_frame',headerSize => 6,
    -      dictID => 0, checksumFlag => false}}
    +
    dictID => 0, checksumFlag => false}}
    @@ -1059,13 +1059,13 @@ which parameters are available and what each parameter does.

    Note that it is not possible to get the dictionary and pledgedSrcSize parameters using this API. Instead you can use get_dict_id/1 on the context/0 to get the id of the dictionary used. There is no way to -get the pledgedSrcSize.

    Returns ok on success, raises an error on failure.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    -{ok, _}
    -2> zstd:get_parameter(CCtx, compressionLevel).
    +get the pledgedSrcSize.

    Returns ok on success, raises an error on failure.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    +{ok, _}
    +2> zstd:get_parameter(CCtx, compressionLevel).
     3
    -3> zstd:set_parameter(CCtx, compressionLevel, 15).
    +3> zstd:set_parameter(CCtx, compressionLevel, 15).
     ok
    -4> zstd:get_parameter(CCtx, compressionLevel).
    +4> zstd:get_parameter(CCtx, compressionLevel).
     15
    @@ -1098,14 +1098,14 @@

    Reset a context while streaming data, returning it to its original state but keeping all parameters set.

    By resetting the state, the context can be re-used for other operations even -if it is in the middle of a (de)compression stream.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    -2> zstd:stream(CCtx, "a").
    -{continue, _}
    -3> zstd:reset(CCtx).
    +if it is in the middle of a (de)compression stream.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    +2> zstd:stream(CCtx, "a").
    +{continue, _}
    +3> zstd:reset(CCtx).
     ok
    -4> {done, Compressed} = zstd:finish(CCtx, "b").
    -5> zstd:decompress(Compressed).
    -[~"b"]
    +4>
    {done, Compressed} = zstd:finish(CCtx, "b"). +5> zstd:decompress(Compressed). +[~"b"]
    @@ -1136,14 +1136,14 @@

    Set a parameter on a context/0.

    See compress_parameters/0 and decompress_parameters/0 for details on -which parameters are available and what each parameter does.

    Returns ok on success, raises an error on failure.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    -{ok, _}
    -2> ok = zstd:set_parameter(CCtx, compressionLevel, 15).
    +which parameters are available and what each parameter does.

    Returns ok on success, raises an error on failure.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    +{ok, _}
    +2> ok = zstd:set_parameter(CCtx, compressionLevel, 15).
     ok
    -3> zstd:stream(CCtx, "abc").
    -{continue, _}
    -4> catch zstd:set_parameter(CCtx, dictionary, "abc").
    -{'EXIT', {{zstd_error, <<"Operation not authorized at current processing stage">>}, _}}
    +3>
    zstd:stream(CCtx, "abc"). +{continue, _} +4> catch zstd:set_parameter(CCtx, dictionary, "abc"). +{'EXIT', {{zstd_error, <<"Operation not authorized at current processing stage">>}, _}}
    @@ -1178,13 +1178,13 @@

    Compress or decompress a stream of data. The last stream of data should be called -with finish/2 to complete the compression/decompression.

    Example:

    1> {ok, CCtx} = zstd:context(compress).
    /usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/erl_syntax.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
    --- old//usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/erl_syntax.html	2026-08-21 04:00:31.590373963 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/erl_syntax.html	2026-08-21 04:00:31.590373963 +0000
    @@ -6931,10 +6931,10 @@
     
     

    Returns the associated post-comments of a node.

    This is a possibly empty list of abstract comments, in top-down textual order. When the code is formatted, post-comments are typically -displayed to the right of and/or below the node. For example:

    {foo, X, Y}     % Post-comment of tuple

    If possible, the comment should be moved past any following separator characters +displayed to the right of and/or below the node. For example:

    {foo, X, Y}     % Post-comment of tuple

    If possible, the comment should be moved past any following separator characters on the same line, rather than placing the separators on the following line. -For example:

    foo([X | Xs], Y) ->
    -    foo(Xs, bar(X));     % Post-comment of 'bar(X)' node
    +For example:

    foo([X | Xs], Y) ->
    +    foo(Xs, bar(X));     % Post-comment of 'bar(X)' node
      ...

    (where the comment is moved past the rightmost ")" and the ";").

    See also: comment/2, get_attrs/1, get_precomments/1, set_postcomments/2.

    @@ -6967,10 +6967,10 @@

    Returns the associated pre-comments of a node.

    This is a possibly empty list of abstract comments, in top-down textual order. When the code is formatted, pre-comments are typically displayed directly above the node. For example:

    % Pre-comment of function
    -foo(X) -> {bar, X}.

    If possible, the comment should be moved before any preceding separator -characters on the same line. For example:

    foo([X | Xs]) ->
    +foo(X) -> {bar, X}.

    If possible, the comment should be moved before any preceding separator +characters on the same line. For example:

    foo([X | Xs]) ->
         % Pre-comment of 'bar(X)' node
    -    [bar(X) | foo(Xs)];
    +    [bar(X) | foo(Xs)];
     ...

    (where the comment is moved before the "[").

    See also: comment/2, get_attrs/1, get_postcomments/1, set_precomments/2.

    /usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/merl.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1976)) --- old//usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/merl.html 2026-08-21 04:00:31.620374158 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/merl.html 2026-08-21 04:00:31.620374158 +0000 @@ -97,30 +97,30 @@ making it easy both to build new ASTs from scratch and to match and decompose existing ASTs. For details that are outside the scope of Merl itself, see the documentation of erl_syntax.

    Quick start

    To enable the full power of Merl, your module needs to include the Merl header -file:

    -include_lib("syntax_tools/include/merl.hrl").

    Then, you can use the ?Q(Text) macros in your code to create ASTs or match on -existing ASTs. For example:

    Tuple = ?Q("{foo, 42}"),
    -?Q("{foo, _@Number}") = Tuple,
    -Call = ?Q("foo:bar(_@Number)")

    Calling merl:print(Call) will then print the following code:

    foo:bar(42)

    The ?Q macros turn the quoted code fragments into ASTs, and lifts +file:

    -include_lib("syntax_tools/include/merl.hrl").

    Then, you can use the ?Q(Text) macros in your code to create ASTs or match on +existing ASTs. For example:

    Tuple = ?Q("{foo, 42}"),
    +?Q("{foo, _@Number}") = Tuple,
    +Call = ?Q("foo:bar(_@Number)")

    Calling merl:print(Call) will then print the following code:

    foo:bar(42)

    The ?Q macros turn the quoted code fragments into ASTs, and lifts metavariables such as _@Tuple and _@Number to the level of your Erlang code, so you can use the corresponding Erlang variables Tuple and Number directly. This is the most straightforward way to use Merl, and in many cases it's all you need.

    You can even write case switches using ?Q macros as patterns. For example:

    case AST of
    -    ?Q("{foo, _@Foo}") -> handle(Foo);
    -    ?Q("{bar, _@Bar}") when erl_syntax:is_integer(Bar) -> handle(Bar);
    -    _ -> handle_default()
    +    ?Q("{foo, _@Foo}") -> handle(Foo);
    +    ?Q("{bar, _@Bar}") when erl_syntax:is_integer(Bar) -> handle(Bar);
    +    _ -> handle_default()
     end

    These case switches only allow ?Q(...) or _ as clause patterns, and the guards may contain any expressions, not just Erlang guard expressions.

    If the macro MERL_NO_TRANSFORM is defined before the merl.hrl header file is included, the parse transform used by Merl will be disabled, and in that case, the match expressions ?Q(...) = ..., case switches using ?Q(...) patterns, and automatic metavariables like _@Tuple cannot be used in your code, but the Merl macros and functions still work. To do metavariable substitution, you need -to use the ?Q(Text, Map) macro. For example:

    Tuple = ?Q("{foo, _@bar, _@baz}", [{bar, Bar}, {baz,Baz}])

    The text given to a ?Q(Text) macro can be either a single string or a list of +to use the ?Q(Text, Map) macro. For example:

    Tuple = ?Q("{foo, _@bar, _@baz}", [{bar, Bar}, {baz,Baz}])

    The text given to a ?Q(Text) macro can be either a single string or a list of strings. The latter is useful when you need to split a long expression over -multiple lines. For example:

    ?Q(["case _@Expr of",
    +multiple lines. For example:

    ?Q(["case _@Expr of",
         "  {foo, X} -> f(X);",
         "  {bar, X} -> g(X)",
         "  _ -> h(X)"
    -"end"])

    If there is a syntax error somewhere in the text (like the missing semicolon in +"end"])

    If there is a syntax error somewhere in the text (like the missing semicolon in the second clause above) this allows Merl to generate an error message pointing to the exact line in your source code. (Just remember to comma-separate the strings in the list, otherwise Erlang will concatenate the string fragments as @@ -137,59 +137,59 @@ uppercase character, as in _@Foo or _@_@Foo, it will become a variable on the Erlang level, and can be used to easily deconstruct and construct syntax trees:

    case Input of
    -    ?Q("{foo, _@Number}") -> ?Q("foo:bar(_@Number)");
    +    ?Q("{foo, _@Number}") -> ?Q("foo:bar(_@Number)");
         ...

    We refer to these as "automatic metavariables". If in addition the name ends with @, as in _@Foo@, the value of the variable as an Erlang term will be automatically converted to the corresponding abstract syntax tree when used to -construct a larger tree. For example, in:

    Bar = {bar, 42},
    -Foo = ?Q("{foo, _@Bar@}")

    (where Bar is just some term, not a syntax tree) the result Foo will be a +construct a larger tree. For example, in:

    Bar = {bar, 42},
    +Foo = ?Q("{foo, _@Bar@}")

    (where Bar is just some term, not a syntax tree) the result Foo will be a syntax tree representing {foo, {bar, 42}}. This avoids the need for temporary -variables in order to inject data, as in

    TmpBar = erl_syntax:abstract(Bar),
    -Foo = ?Q("{foo, _@TmpBar}")

    If the context requires an integer rather than a variable, an atom, or a string, +variables in order to inject data, as in

    TmpBar = erl_syntax:abstract(Bar),
    +Foo = ?Q("{foo, _@TmpBar}")

    If the context requires an integer rather than a variable, an atom, or a string, you cannot use the uppercase convention to mark an automatic metavariable. Instead, if the integer (without the 909-prefix and lift/glob markers) ends in a 9, the integer will become an Erlang-level variable prefixed with Q, and if it ends with 99 it will also be automatically abstracted. For example, the following will increment the arity of the exported function f:

    case Form of
    -    ?Q("-export([f/90919]).") ->
    -        Q2 = erl_syntax:concrete(Q1) + 1,
    -        ?Q("-export([f/909299]).");
    +    ?Q("-export([f/90919]).") ->
    +        Q2 = erl_syntax:concrete(Q1) + 1,
    +        ?Q("-export([f/909299]).");
         ...

    When to use the various forms of metavariables

    Merl can only parse a fragment of text if it follows the basic syntactical rules of Erlang. In most places, a normal Erlang variable can be used as metavariable, -for example:

    ?Q("f(_@Arg)") = Expr

    but if you want to match on something like the name of a function, you have to -use an atom as metavariable:

    ?Q("'@Name'() -> _@@_." = Function

    (note the anonymous glob variable _@@_ to ignore the function body).

    In some contexts, only a string or an integer is allowed. For example, the +for example:

    ?Q("f(_@Arg)") = Expr

    but if you want to match on something like the name of a function, you have to +use an atom as metavariable:

    ?Q("'@Name'() -> _@@_." = Function

    (note the anonymous glob variable _@@_ to ignore the function body).

    In some contexts, only a string or an integer is allowed. For example, the directive -file(Name, Line) requires that Name is a string literal and -Line an integer literal:

    ?Q("-file(\"'@File\", 9090).") = ?Q("-file(\"foo.erl\", 42).")).

    This will extract the string literal "foo.erl" into the variable Foo. Note +Line an integer literal:

    ?Q("-file(\"'@File\", 9090).") = ?Q("-file(\"foo.erl\", 42).")).

    This will extract the string literal "foo.erl" into the variable Foo. Note the use of the anonymous variable 9090 to ignore the line number. To match and also bind a metavariable that must be an integer literal, we can use the convention of ending the integer with a 9, turning it into a Q-prefixed variable on the Erlang level (see the previous section).

    Globs

    Whenever you want to match out a number of elements in a sequence (zero or more) -rather than a fixed set of elements, you need to use a glob. For example:

    ?Q("{_@@Elements}") = ?Q({a, b, c})

    will bind Elements to the list of individual syntax trees representing the atoms +rather than a fixed set of elements, you need to use a glob. For example:

    ?Q("{_@@Elements}") = ?Q({a, b, c})

    will bind Elements to the list of individual syntax trees representing the atoms a, b, and c. This can also be used with static prefix and suffix elements -in the sequence. For example:

    ?Q("{a, b, _@@Elements}") = ?Q({a, b, c, d})

    will bind Elements to the list of the c and d subtrees, and

    ?Q("{_@@Elements, c, d}") = ?Q({a, b, c, d})

    will bind Elements to the list of the a and b subtrees. You can even use -plain metavariables in the prefix or suffix:

    ?Q("{_@First, _@@Rest}") = ?Q({a, b, c})

    or

    ?Q("{_@@_, _@Last}") = ?Q({a, b, c})

    (ignoring all but the last element). However, you cannot have two globs as part +in the sequence. For example:

    ?Q("{a, b, _@@Elements}") = ?Q({a, b, c, d})

    will bind Elements to the list of the c and d subtrees, and

    ?Q("{_@@Elements, c, d}") = ?Q({a, b, c, d})

    will bind Elements to the list of the a and b subtrees. You can even use +plain metavariables in the prefix or suffix:

    ?Q("{_@First, _@@Rest}") = ?Q({a, b, c})

    or

    ?Q("{_@@_, _@Last}") = ?Q({a, b, c})

    (ignoring all but the last element). However, you cannot have two globs as part of the same sequence.

    Lifted metavariables

    In some cases, the Erlang syntax rules make it impossible to place a -metavariable directly where you would like it. For example, you cannot write:

    ?Q("-export([_@@Name]).")

    to match out all name/arity pairs in the export list, or to insert a list of +metavariable directly where you would like it. For example, you cannot write:

    ?Q("-export([_@@Name]).")

    to match out all name/arity pairs in the export list, or to insert a list of exports in a declaration, because the Erlang parser only allows elements on the form A/I (where A is an atom and I an integer) in the export list. A variable like the above is not allowed, but neither is a single atom or integer, so '@@Name' or 909919 would not work either.

    What you have to do in such cases is to write your metavariable in a syntactically valid position, and use lifting markers to denote where it should -really apply, as in:

    ?Q("-export(['@_@Name'/0]).")

    This causes the variable to be lifted (after parsing) to the next higher level +really apply, as in:

    ?Q("-export(['@_@Name'/0]).")

    This causes the variable to be lifted (after parsing) to the next higher level in the syntax tree, replacing that entire subtree. In this case, the '@_@Name'/0 will be replaced with '@@Name', and the /0 part was just used as dummy notation and will be discarded.

    You may even need to apply lifting more than once. To match the entire export -list as a single syntax tree, you can write:

    ?Q("-export(['@__Name'/0]).")

    using two underscores, but with no glob marker this time. This will make the +list as a single syntax tree, you can write:

    ?Q("-export(['@__Name'/0]).")

    using two underscores, but with no glob marker this time. This will make the entire ['@__Name'/0] part be replaced with '@Name'.

    Sometimes, the tree structure of a code fragment is not very obvious, and parts of the structure may be invisible when printed as source code. For instance, a -simple function definition like the following:

    zero() -> 0.

    consists of the name (the atom zero), and a list of clauses containing the +simple function definition like the following:

    zero() -> 0.

    consists of the name (the atom zero), and a list of clauses containing the single clause () -> 0. The clause consists of an argument list (empty), a guard (empty), and a body (which is always a list of expressions) containing the single expression 0. This means that to match out the name and the list of clauses of any function, you'll need to use a pattern like ?Q("'@Name'() -> _@_@Body."), using a dummy clause whose body is a glob lifted one level.

    To visualize the structure of a syntax tree, you can use the function -merl:show(T), which prints a summary. For example, entering

    merl:show(merl:quote("inc(X, Y) when Y > 0 -> X + Y."))

    in the Erlang shell will print the following (where the + signs separate +merl:show(T), which prints a summary. For example, entering

    merl:show(merl:quote("inc(X, Y) when Y > 0 -> X + Y."))

    in the Erlang shell will print the following (where the + signs separate groups of subtrees on the same level):

    function: inc(X, Y) when ... -> X + Y.
       atom: inc
       +
    /usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (6897))
    --- old//usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/notes.html	2026-08-21 04:00:31.646374328 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/syntax_tools-4.0.3/doc/html/notes.html	2026-08-21 04:00:31.646374328 +0000
    @@ -89,13 +89,13 @@
       
     
     
    -

    This document describes the changes made to the Syntax_Tools application.

    Syntax_Tools 4.0.3

    Fixed Bugs and Malfunctions

    • Corrected the af_zip_generator() type in the parser and syntax_tools.

      Own Id: OTP-19939

    Improvements and New Features

    • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

      A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

      make release_docs places the documentation in the released code under the doc folder.

      make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

      The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

      Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

      Improves the source Software-Bill-of-Materials

      • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
      • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
      • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

      Own Id: OTP-19886 Aux Id: PR-10434

    Syntax_Tools 4.0.2

    Fixed Bugs and Malfunctions

    • Annotate map comprehensions and generators

      Own Id: OTP-19817 Aux Id: GH-10119

    Syntax_Tools 4.0.1

    Fixed Bugs and Malfunctions

    • Fixed zip generator crash in annotate_bindings/1

      Own Id: OTP-19731 Aux Id: GH-10102, PR-10104

    Syntax_Tools 4.0

    Fixed Bugs and Malfunctions

    • A few minor issues were corrected in m:syntax_tools, as well in the erl_anno module.

      Own Id: OTP-19422 Aux Id: PR-9253

    Improvements and New Features

    • Comprehensions have been extended with zip generators according to EEP 73.

      Example:

      1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
      -[5,7,9]

      Own Id: OTP-19184 Aux Id: PR-8926

    • New strict generators have been added for comprehensions.

      The currently existing generators are "relaxed": they ignore terms in the +

      This document describes the changes made to the Syntax_Tools application.

      Syntax_Tools 4.0.3

      Fixed Bugs and Malfunctions

      • Corrected the af_zip_generator() type in the parser and syntax_tools.

        Own Id: OTP-19939

      Improvements and New Features

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      Syntax_Tools 4.0.2

      Fixed Bugs and Malfunctions

      • Annotate map comprehensions and generators

        Own Id: OTP-19817 Aux Id: GH-10119

      Syntax_Tools 4.0.1

      Fixed Bugs and Malfunctions

      • Fixed zip generator crash in annotate_bindings/1

        Own Id: OTP-19731 Aux Id: GH-10102, PR-10104

      Syntax_Tools 4.0

      Fixed Bugs and Malfunctions

      • A few minor issues were corrected in m:syntax_tools, as well in the erl_anno module.

        Own Id: OTP-19422 Aux Id: PR-9253

      Improvements and New Features

      • Comprehensions have been extended with zip generators according to EEP 73.

        Example:

        1> [A+B || A <- [1,2,3] && B <- [4,5,6]].
        +[5,7,9]

        Own Id: OTP-19184 Aux Id: PR-8926

      • New strict generators have been added for comprehensions.

        The currently existing generators are "relaxed": they ignore terms in the right-hand side expression that do not match the left-hand side pattern.

        The new strict generators fail with exception badmatch if a pattern doesn't match.

        Examples:

        Using the current relaxed generator operator <-, any element not matching -the pattern {_,_} will be silently discarded:

        1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
        -[{ok,1},{error,2}]

        If the intention is that all lists processed by a list comprehension must only +the pattern {_,_} will be silently discarded:

        1> [T || {_,_}=T <- [{ok,1},ok,{error,2}]].
        +[{ok,1},{error,2}]

        If the intention is that all lists processed by a list comprehension must only contain tuples of size two, using the new strict version of the operator ensures -that term not matching will cause a crash:

        2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
        +that term not matching will cause a crash:

        2> [T || {_,_}=T <:- [{ok,1},ok,{error,2}]].
         ** exception error: no match of right hand side value ok

        Using the strict generator operator to mark the intention that all list elements must match the pattern could help finding mistakes quicker if something unpexected is added to the list processed by the generator.

        The strict version for bitstring generators is <:=.

        Own Id: OTP-19317 Aux Id: PR-8625

      • Fixed licenses in files and added ORT curations to the following apps: otp, eldap, erl_interface, eunit, parsetools, stdlib, syntax_tools, and ERTS.

        Own Id: OTP-19478 Aux Id: PR-9376, PR-9402, PR-9819

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      Syntax_Tools 3.2.2.2

      Fixed Bugs and Malfunctions

      • Annotate map comprehensions and generators

        Own Id: OTP-19817 Aux Id: GH-10119

      Syntax_Tools 3.2.2.1

      Fixed Bugs and Malfunctions

      • Backport fix for annotating maybe to OTP-27

        Own Id: OTP-19740 Aux Id: GH-10103, PR-10118

      Syntax_Tools 3.2.2

      Fixed Bugs and Malfunctions

      • Annotation of maybe expressions has been corrected.

        Own Id: OTP-19405 Aux Id: PR-8811

      Syntax_Tools 3.2.1

      Fixed Bugs and Malfunctions

      • The documentation for syntax_tools has been polished after the migration to the new documentation system.

        Own Id: OTP-19102 Aux Id: PR-8515

      Syntax_Tools 3.2

      Fixed Bugs and Malfunctions

      • The epp_dodger module can now handle the maybe and else keywords.

        Own Id: OTP-18608 Aux Id: GH-7266, PR-7267

      • Reverting a #href_anchor"https://github.com/erlang/otp/pull/7398" title="">PR-7398

      Improvements and New Features

      Syntax_Tools 3.1.0.1

      Fixed Bugs and Malfunctions

      • Annotate map comprehensions and generators

        Own Id: OTP-19817 Aux Id: GH-10119

      Syntax_Tools 3.1

      Improvements and New Features

      • Map comprehensions as suggested in EEP 58 has now been implemented.

        Own Id: OTP-18413 Aux Id: EEP-58, PR-6727

      Syntax_Tools 3.0.1

      Fixed Bugs and Malfunctions

      • erl_syntax_lib:annotate_bindings/1,2 will now properly annotate named functions and their arguments.

        Own Id: OTP-18380 Aux Id: PR-6523, GH-4733

      Syntax_Tools 3.0

      Fixed Bugs and Malfunctions

      • The erl_syntax_lib:analyze_attribute/1 function would return {Name, {Name, Value}} instead of {Name, Value} (which is the documented /usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/getting_started.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1248)) --- old//usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/getting_started.html 2026-08-21 04:00:31.664374445 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/getting_started.html 2026-08-21 04:00:31.665374451 +0000 @@ -92,10 +92,10 @@

        The start/1 function starts a daemon process listening for UDP packets on a port. When it receives a request for read or write, it spawns a temporary server process handling the transfer.

        This is a simple example of starting the TFTP server and reading the content of -a sample file using the TFTP client.

        Step 1. Create a sample file to be used for the transfer:

              $ echo "Erlang/OTP 21" > /tmp/file.txt

        Step 2. Start the TFTP server:

              1> Callback = {callback,{"",tftp_file,[{root_dir,"/tmp"}]}}.
        -      2> {ok, Pid} = tftp:start([{port, 19999}, Callback]).
        -      {ok,<0.65.0>}

        Step 3. Start the TFTP client (in another shell):

              1> tftp:read_file("file.txt", binary, [{port, 19999}]).
        -      {ok,<<"Erlang/OTP 21\n">>}
        +a sample file using the TFTP client.

        Step 1. Create a sample file to be used for the transfer:

              $ echo "Erlang/OTP 21" > /tmp/file.txt

        Step 2. Start the TFTP server:

              1> Callback = {callback,{"",tftp_file,[{root_dir,"/tmp"}]}}.
        +      2> {ok, Pid} = tftp:start([{port, 19999}, Callback]).
        +      {ok,<0.65.0>}

        Step 3. Start the TFTP client (in another shell):

              1> tftp:read_file("file.txt", binary, [{port, 19999}]).
        +      {ok,<<"Erlang/OTP 21\n">>}
        /usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/tftp.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/tftp.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/tftp.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> tftp - 1.2.4 - urn:uuid:9f0bad20-6d17-95f9-68f1-d51b213ae7e6 + urn:uuid:569c25e3-b248-3d01-9908-1fc33b04dfc8 en - 2026-08-21T03:49:59Z + 2042-09-22T17:09:01Z /usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/tftp.epub/OEBPS/getting_started.xhtml differs (HTML document, ASCII text, with very long lines (1248)) --- old//usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/tftp.epub/OEBPS/getting_started.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tftp-1.2.4/doc/html/tftp.epub/OEBPS/getting_started.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -20,10 +20,10 @@

        The start/1 function starts a daemon process listening for UDP packets on a port. When it receives a request for read or write, it spawns a temporary server process handling the transfer.

        This is a simple example of starting the TFTP server and reading the content of -a sample file using the TFTP client.

        Step 1. Create a sample file to be used for the transfer:

              $ echo "Erlang/OTP 21" > /tmp/file.txt

        Step 2. Start the TFTP server:

              1> Callback = {callback,{"",tftp_file,[{root_dir,"/tmp"}]}}.
        -      2> {ok, Pid} = tftp:start([{port, 19999}, Callback]).
        -      {ok,<0.65.0>}

        Step 3. Start the TFTP client (in another shell):

              1> tftp:read_file("file.txt", binary, [{port, 19999}]).
        -      {ok,<<"Erlang/OTP 21\n">>}
        +a sample file using the TFTP client.

        Step 1. Create a sample file to be used for the transfer:

              $ echo "Erlang/OTP 21" > /tmp/file.txt

        Step 2. Start the TFTP server:

              1> Callback = {callback,{"",tftp_file,[{root_dir,"/tmp"}]}}.
        +      2> {ok, Pid} = tftp:start([{port, 19999}, Callback]).
        +      {ok,<0.65.0>}

        Step 3. Start the TFTP client (in another shell):

              1> tftp:read_file("file.txt", binary, [{port, 19999}]).
        +      {ok,<<"Erlang/OTP 21\n">>}
        /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cover.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cover.html 2026-08-21 04:00:31.756375044 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cover.html 2026-08-21 04:00:31.756375044 +0000 @@ -1520,7 +1520,7 @@ call is equivalent to analyse('_', coverage, Arg).

        Otherwise Arg is assumed to be a module name, and this call is equivalent to analyse(Arg, coverage, function).

        Note

        To analyze a module whose name overlaps with one the values in analysis() or level(), the module -name has to be in a list. For example, to analyze a module named calls:

        cover:analyse([calls]).
        +name has to be in a list. For example, to analyze a module named calls:

        cover:analyse([calls]).
        @@ -1562,7 +1562,7 @@ analyse(Arg1, Arg2, function).

        If Arg2 is one of the values in level(), Arg1 is assumed to be a module and this call is equivalent to analyse(Arg1, coverage, Arg2).

        Note

        To analyze a module whose name overlaps with one of the values in analysis(), the module name needs to be in a -list. For example, to analyze a module named calls:

        cover:analyse([calls], function).
        +list. For example, to analyze a module named calls:

        cover:analyse([calls], function).
        @@ -1671,7 +1671,7 @@ options, this call is equivalent to analyse_to_file('_', Arg).

        Otherwise Arg is assumed to be a module, and this call is equivalent to analyse_to_file(Arg, []).

        Note

        To analyze a module of the name html (which overlaps with an option in analyse_option()), it is necessary to -use cover:analyse_to_file/2:

        cover:analyse_to_file([html], []).
        +use cover:analyse_to_file/2:

        cover:analyse_to_file([html], []).
        /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cover_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1033)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cover_chapter.html 2026-08-21 04:00:31.782375213 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cover_chapter.html 2026-08-21 04:00:31.782375213 +0000 @@ -92,75 +92,75 @@

        Introduction

        The module cover provides a set of functions for coverage analysis of Erlang programs, counting how many times each executable line is executed.

        Coverage analysis can be used to verify test cases, making sure all relevant -code is covered, and can be helpful when looking for bottlenecks in the code.

        Getting Started With Cover

        Example

        Assume that a test case for the following program should be verified:

        -module(channel).
        --behaviour(gen_server).
        +code is covered, and can be helpful when looking for bottlenecks in the code.

        Getting Started With Cover

        Example

        Assume that a test case for the following program should be verified:

        -module(channel).
        +-behaviour(gen_server).
         
        --export([start_link/0,stop/0]).
        --export([alloc/0,free/1]). % client interface
        --export([init/1,handle_call/3,terminate/2]). % callback functions
        +-export([start_link/0,stop/0]).
        +-export([alloc/0,free/1]). % client interface
        +-export([init/1,handle_call/3,terminate/2]). % callback functions
         
        -start_link() ->
        -    gen_server:start_link({local,channel}, channel, [], []).
        +start_link() ->
        +    gen_server:start_link({local,channel}, channel, [], []).
         
        -stop() ->
        -    gen_server:call(channel, stop).
        +stop() ->
        +    gen_server:call(channel, stop).
         
         %%%-Client interface functions-------------------------------------------
         
        -alloc() ->
        -    gen_server:call(channel, alloc).
        +alloc() ->
        +    gen_server:call(channel, alloc).
         
        -free(Channel) ->
        -    gen_server:call(channel, {free,Channel}).
        +free(Channel) ->
        +    gen_server:call(channel, {free,Channel}).
         
         %%%-gen_server callback functions----------------------------------------
         
        -init(_Arg) ->
        -    {ok,channels()}.
        +init(_Arg) ->
        +    {ok,channels()}.
         
        -handle_call(stop, _Client, Channels) ->
        -    {stop,normal,ok,Channels};
        +handle_call(stop, _Client, Channels) ->
        +    {stop,normal,ok,Channels};
         
        -handle_call(alloc, _Client, Channels) ->
        -    {Ch,Channels2} = alloc(Channels),
        -    {reply,{ok,Ch},Channels2};
        +handle_call(alloc, _Client, Channels) ->
        +    {Ch,Channels2} = alloc(Channels),
        +    {reply,{ok,Ch},Channels2};
         
        -handle_call({free,Channel}, _Client, Channels) ->
        -    Channels2 = free(Channel, Channels),
        -    {reply,ok,Channels2}.
        +handle_call({free,Channel}, _Client, Channels) ->
        +    Channels2 = free(Channel, Channels),
        +    {reply,ok,Channels2}.
         
        -terminate(_Reason, _Channels) ->
        +terminate(_Reason, _Channels) ->
             ok.
         
         %%%-Internal functions---------------------------------------------------
         
        -channels() ->
        -    [ch1,ch2,ch3].
        +channels() ->
        +    [ch1,ch2,ch3].
         
        -alloc([Channel|Channels]) ->
        -    {Channel,Channels};
        -alloc([]) ->
        +alloc([Channel|Channels]) ->
        +    {Channel,Channels};
        +alloc([]) ->
             false.
         
        -free(Channel, Channels) ->
        -    [Channel|Channels].

        The test case is implemented as follows:

        -module(test).
        --export([s/0]).
        -
        -s() ->
        -    {ok,Pid} = channel:start_link(),
        -    {ok,Ch1} = channel:alloc(),
        -    ok = channel:free(Ch1),
        -    ok = channel:stop().

        Preparation

        First of all, Cover must be started. This spawns a process which owns the Cover -database where all coverage data will be stored.

        1> cover:start().
        -{ok,<0.90.0>}

        To include other nodes in the coverage analysis, use +free(Channel, Channels) -> + [Channel|Channels].

        The test case is implemented as follows:

        -module(test).
        +-export([s/0]).
        +
        +s() ->
        +    {ok,Pid} = channel:start_link(),
        +    {ok,Ch1} = channel:alloc(),
        +    ok = channel:free(Ch1),
        +    ok = channel:stop().

        Preparation

        First of all, Cover must be started. This spawns a process which owns the Cover +database where all coverage data will be stored.

        1> cover:start().
        +{ok,<0.90.0>}

        To include other nodes in the coverage analysis, use cover:start/1. All cover-compiled modules will then be loaded on all nodes, and data from all nodes will be summed up when analysing. For simplicity this example only involves the current node.

        Before any analysis can take place, the involved modules must be cover-compiled. This means that some extra information is added to the module before beging compiled into a binary and loaded. The source file of the module is -not affected and no .beam file is created.

        2> cover:compile_module(channel).
        -{ok,channel}

        Each time a function in the cover-compiled module channel is called, +not affected and no .beam file is created.

        2> cover:compile_module(channel).
        +{ok,channel}

        Each time a function in the cover-compiled module channel is called, information about the call will be added to the Cover database. Run the test case:

        3> test:s().
         ok

        Cover analysis is performed by examining the contents of the Cover database. The @@ -172,174 +172,174 @@ {Cov,NotCov}, where Cov is the number of executable lines that have been executed at least once and NotCov is the number of executable lines that have not been executed.

        If the analysis is made on module level, the result is given for the entire -module as a tuple {Module,{Cov,NotCov}}:

        4> cover:analyse(channel, coverage, module).
        -{ok,{channel,{14,1}}}

        For channel, the result shows that 14 lines in the module are covered but one +module as a tuple {Module,{Cov,NotCov}}:

        4> cover:analyse(channel, coverage, module).
        +{ok,{channel,{14,1}}}

        For channel, the result shows that 14 lines in the module are covered but one line is not covered.

        If the analysis is made on function level, the result is given as a list of tuples {Function,{Cov,NotCov}}, one for each function in the module. A -function is specified by its module name, function name and arity:

        5> cover:analyse(channel, coverage, function).
        -{ok,[{{channel,start_link,0},{1,0}},
        -     {{channel,stop,0},{1,0}},
        -     {{channel,alloc,0},{1,0}},
        -     {{channel,free,1},{1,0}},
        -     {{channel,init,1},{1,0}},
        -     {{channel,handle_call,3},{5,0}},
        -     {{channel,terminate,2},{1,0}},
        -     {{channel,channels,0},{1,0}},
        -     {{channel,alloc,1},{1,1}},
        -     {{channel,free,2},{1,0}}]}

        For channel, the result shows that the uncovered line is in the function +function is specified by its module name, function name and arity:

        5> cover:analyse(channel, coverage, function).
        +{ok,[{{channel,start_link,0},{1,0}},
        +     {{channel,stop,0},{1,0}},
        +     {{channel,alloc,0},{1,0}},
        +     {{channel,free,1},{1,0}},
        +     {{channel,init,1},{1,0}},
        +     {{channel,handle_call,3},{5,0}},
        +     {{channel,terminate,2},{1,0}},
        +     {{channel,channels,0},{1,0}},
        +     {{channel,alloc,1},{1,1}},
        +     {{channel,free,2},{1,0}}]}

        For channel, the result shows that the uncovered line is in the function channel:alloc/1.

        If the analysis is made on clause level, the result is given as a list of tuples {Clause,{Cov,NotCov}}, one for each function clause in the module. A clause is specified by its module name, function name, arity and position within the -function definition:

        6> cover:analyse(channel, coverage, clause).
        -{ok,[{{channel,start_link,0,1},{1,0}},
        -     {{channel,stop,0,1},{1,0}},
        -     {{channel,alloc,0,1},{1,0}},
        -     {{channel,free,1,1},{1,0}},
        -     {{channel,init,1,1},{1,0}},
        -     {{channel,handle_call,3,1},{1,0}},
        -     {{channel,handle_call,3,2},{2,0}},
        -     {{channel,handle_call,3,3},{2,0}},
        -     {{channel,terminate,2,1},{1,0}},
        -     {{channel,channels,0,1},{1,0}},
        -     {{channel,alloc,1,1},{1,0}},
        -     {{channel,alloc,1,2},{0,1}},
        -     {{channel,free,2,1},{1,0}}]}

        For channel, the result shows that the uncovered line is in the second clause +function definition:

        6> cover:analyse(channel, coverage, clause).
        +{ok,[{{channel,start_link,0,1},{1,0}},
        +     {{channel,stop,0,1},{1,0}},
        +     {{channel,alloc,0,1},{1,0}},
        +     {{channel,free,1,1},{1,0}},
        +     {{channel,init,1,1},{1,0}},
        +     {{channel,handle_call,3,1},{1,0}},
        +     {{channel,handle_call,3,2},{2,0}},
        +     {{channel,handle_call,3,3},{2,0}},
        +     {{channel,terminate,2,1},{1,0}},
        +     {{channel,channels,0,1},{1,0}},
        +     {{channel,alloc,1,1},{1,0}},
        +     {{channel,alloc,1,2},{0,1}},
        +     {{channel,free,2,1},{1,0}}]}

        For channel, the result shows that the uncovered line is in the second clause of channel:alloc/1.

        Finally, if the analysis is made on line level, the result is given as a list of tuples {Line,{Cov,NotCov}}, one for each executable line in the source code. A -line is specified by its module name and line number.

        7> cover:analyse(channel, coverage, line).
        -{ok,[{{channel,9},{1,0}},
        -     {{channel,12},{1,0}},
        -     {{channel,17},{1,0}},
        -     {{channel,20},{1,0}},
        -     {{channel,25},{1,0}},
        -     {{channel,28},{1,0}},
        -     {{channel,31},{1,0}},
        -     {{channel,32},{1,0}},
        -     {{channel,35},{1,0}},
        -     {{channel,36},{1,0}},
        -     {{channel,39},{1,0}},
        -     {{channel,44},{1,0}},
        -     {{channel,47},{1,0}},
        -     {{channel,49},{0,1}},
        /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cprof.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1243))
        --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cprof.html	2026-08-21 04:00:31.809375389 +0000
        +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cprof.html	2026-08-21 04:00:31.808375382 +0000
        @@ -555,7 +555,7 @@
         
               
         
        -

        Collects and analyses all call counters for module Module.

        This function returns:

        {Module, ModuleCount, FuncAnalysisList}

        where FuncAnalysisList is a list of tuples, one for each function:

        {{Module, FunctionName, Arity}, FuncCallCount}

        If call counters are still running while analyse/0,1,2 is executing, the result +

        Collects and analyses all call counters for module Module.

        This function returns:

        {Module, ModuleCount, FuncAnalysisList}

        where FuncAnalysisList is a list of tuples, one for each function:

        {{Module, FunctionName, Arity}, FuncCallCount}

        If call counters are still running while analyse/0,1,2 is executing, the result could be inconsistent. This happens if the process executing analyse/0,1,2 is scheduled out so some other process can increment the counters that are being analysed. Calling pause() before analysing takes care of /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cprof_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1636)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cprof_chapter.html 2026-08-21 04:00:31.831375532 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/cprof_chapter.html 2026-08-21 04:00:31.831375532 +0000 @@ -114,110 +114,110 @@ cprof itself; the only way to analyze cprof is by specifying it as a single module to analyse.

        Call count tracing is very lightweight compared to other forms of tracing since no trace message has to be generated. Some measurements indicates performance -degradations in the vicinity of 10 percent.

        The following sections show some examples of profiling with cprof.

        Example: Background work

        From the Erlang shell:

        1> cprof:start(), cprof:pause(). % Stop counters just after start
        +degradations in the vicinity of 10 percent.

        The following sections show some examples of profiling with cprof.

        Example: Background work

        From the Erlang shell:

        1> cprof:start(), cprof:pause(). % Stop counters just after start
         8492
        -2> cprof:analyse().
        -{539,
        - [{shell,155,
        -         [{{shell,prep_check,1},55},
        -          {{shell,used_records,4},45},
        -          {{shell,used_records,1},45},
        -          {{shell,used_record_defs,2},1},
        -          {{shell,record_defs,2},1},
        -          {{shell,record_bindings,2},1},
        -          {{shell,exprs,7},1},
        -          {{shell,expr,4},1},
        -          {{shell,expand_records,2},1},
        -          {{shell,check_command,2},1},
        -          {{shell,apply_fun,3},1},
        -          {{shell,'-exprs/7-lc$^0/1-0-',1},1},
        -          {{shell,'-eval_loop/3-fun-0-',3},1}]},
        +2> cprof:analyse().
        +{539,
        + [{shell,155,
        +         [{{shell,prep_check,1},55},
        +          {{shell,used_records,4},45},
        +          {{shell,used_records,1},45},
        +          {{shell,used_record_defs,2},1},
        +          {{shell,record_defs,2},1},
        +          {{shell,record_bindings,2},1},
        +          {{shell,exprs,7},1},
        +          {{shell,expr,4},1},
        +          {{shell,expand_records,2},1},
        +          {{shell,check_command,2},1},
        +          {{shell,apply_fun,3},1},
        +          {{shell,'-exprs/7-lc$^0/1-0-',1},1},
        +          {{shell,'-eval_loop/3-fun-0-',3},1}]},
           %% Information about many modules omitted.
                              .
                              .
                              .
           %% Here is the last part.
        -  {erts_internal,2,[{{erts_internal,trace_pattern,3},2}]},
        -  {otp_internal,1,[{{otp_internal,obsolete,3},1}]},
        -  {maps,1,[{{maps,from_list,1},1}]},
        -  {erl_internal,1,[{{erl_internal,bif,3},1}]}]}
        -3> cprof:analyse(cprof).
        -{cprof,3,[{{cprof,tr,2},2},{{cprof,pause,0},1}]}
        -4> cprof:stop().
        +  {erts_internal,2,[{{erts_internal,trace_pattern,3},2}]},
        +  {otp_internal,1,[{{otp_internal,obsolete,3},1}]},
        +  {maps,1,[{{maps,from_list,1},1}]},
        +  {erl_internal,1,[{{erl_internal,bif,3},1}]}]}
        +3> cprof:analyse(cprof).
        +{cprof,3,[{{cprof,tr,2},2},{{cprof,pause,0},1}]}
        +4> cprof:stop().
         8586

        The example showed some of the background work that the shell performs just to interpret the first command line.

        What is captured in this example is the part of the work the shell does while interpreting the command line that occurs between the actual calls to -cprof:start() and cprof:analyse().

        Example: One module

        From the Erlang shell:

        1> cprof:start(),R=calendar:day_of_the_week(1896,4,27),cprof:pause(),R.
        +cprof:start() and cprof:analyse().

        Example: One module

        From the Erlang shell:

        1> cprof:start(),R=calendar:day_of_the_week(1896,4,27),cprof:pause(),R.
         1
        -2> cprof:analyse(calendar).
        -{calendar,9,
        -          [{{calendar,last_day_of_the_month1,2},1},
        -           {{calendar,last_day_of_the_month,2},1},
        -           {{calendar,is_leap_year1,1},1},
        -           {{calendar,is_leap_year,1},1},
        -           {{calendar,dy,1},1},
        -           {{calendar,dm,1},1},
        -           {{calendar,df,2},1},
        -           {{calendar,day_of_the_week,3},1},
        -           {{calendar,date_to_gregorian_days,3},1}]}
        -3> cprof:stop().
        +2> cprof:analyse(calendar).
        +{calendar,9,
        +          [{{calendar,last_day_of_the_month1,2},1},
        +           {{calendar,last_day_of_the_month,2},1},
        +           {{calendar,is_leap_year1,1},1},
        +           {{calendar,is_leap_year,1},1},
        +           {{calendar,dy,1},1},
        +           {{calendar,dm,1},1},
        +           {{calendar,df,2},1},
        +           {{calendar,day_of_the_week,3},1},
        +           {{calendar,date_to_gregorian_days,3},1}]}
        +3> cprof:stop().
         8648

        The example tells us that "Aktiebolaget LM Ericsson & Co" was registered on a Monday (since the return value of the first command is 1), and that the calendar module needed 9 function calls to calculate that.

        Using cprof:analyse() in this example also shows approximately the same -background work as in the first example.

        Example: In the code

        Write a module:

        -module(sort).
        --export([do/1]).
        +background work as in the first example.

        Example: In the code

        Write a module:

        -module(sort).
        +-export([do/1]).
         
        -do(N) ->
        -    cprof:stop(),
        -    cprof:start(),
        -    do(N, []).
        +do(N) ->
        +    cprof:stop(),
        +    cprof:start(),
        +    do(N, []).
         
        -do(0, L) ->
        -    R = lists:sort(L),
        -    cprof:pause(),
        +do(0, L) ->
        +    R = lists:sort(L),
        +    cprof:pause(),
             R;
        -do(N, L) ->
        -    do(N-1, [rand:uniform(256)-1 | L]).

        From the Erlang shell:

        1> c(sort).
        -{ok,sort}
        -2> rand:seed(default, 42), ok.
        +do(N, L) ->
        +    do(N-1, [rand:uniform(256)-1 | L]).

        From the Erlang shell:

        1> c(sort).
        +{ok,sort}
        +2> rand:seed(default, 42), ok.
         ok.
        -3> sort:do(1000).
        -[0,0,0,1,1,1,1,2,2,3,3,4,4,4,4,5,5,5,6,6,6,6,7,7,7,7,7,8,8|...]
        -4> cprof:analyse().
        -{13180,
        - [{lists,6173,
        -         [{{lists,rmerge3_1,6},1045},
        -          {{lists,rmerge3_2,6},977},
        -          {{lists,split_1,5},652},
        -          {{lists,merge3_1,6},579},
        -          {{lists,merge3_2,6},577},
        -          {{lists,rmerge3_12_3,6},511},
        -          {{lists,split_1_1,6},347},
        -          {{lists,merge3_12_3,6},310},
        -          {{lists,rmerge3_21_3,6},282},
        -          {{lists,merge3_21_3,6},221},
        -          {{lists,merge2_1,4},154},
        -          {{lists,merge2_2,5},138},
        -          {{lists,reverse,2},106},
        -          {{lists,rmerge2_2,5},87},
        -          {{lists,rmergel,2},81},
        -          {{lists,rmerge2_1,4},75},
        -          {{lists,mergel,2},28},
        -          {{lists,keyfind,3},2},
        -          {{lists,sort,1},1}]},
        -  {rand,5000,
        -        [{{rand,uniform_s,2},1000},
        -         {{rand,uniform,1},1000},
        -         {{rand,seed_put,1},1000},
        -         {{rand,seed_get,0},1000},
        -         {{rand,exsss_uniform,2},1000}]},
        -  {erlang,1004,
        -          [{{erlang,put,2},1000},
        -           {{erlang,trace_pattern,3},2},
        -           {{erlang,ensure_tracer_module_loaded,2},2}]},
        -  {sort,1001,[{{sort,do,2},1001}]},
        -  {erts_internal,2,[{{erts_internal,trace_pattern,3},2}]}]}
        -5> cprof:stop().
        +3> sort:do(1000).
        +[0,0,0,1,1,1,1,2,2,3,3,4,4,4,4,5,5,5,6,6,6,6,7,7,7,7,7,8,8|...]
        +4> cprof:analyse().
        +{13180,
        + [{lists,6173,
        +         [{{lists,rmerge3_1,6},1045},
        +          {{lists,rmerge3_2,6},977},
        +          {{lists,split_1,5},652},
        +          {{lists,merge3_1,6},579},
        +          {{lists,merge3_2,6},577},
        +          {{lists,rmerge3_12_3,6},511},
        +          {{lists,split_1_1,6},347},
        +          {{lists,merge3_12_3,6},310},
        +          {{lists,rmerge3_21_3,6},282},
        +          {{lists,merge3_21_3,6},221},
        +          {{lists,merge2_1,4},154},
        +          {{lists,merge2_2,5},138},
        +          {{lists,reverse,2},106},
        +          {{lists,rmerge2_2,5},87},
        +          {{lists,rmergel,2},81},
        +          {{lists,rmerge2_1,4},75},
        +          {{lists,mergel,2},28},
        +          {{lists,keyfind,3},2},
        +          {{lists,sort,1},1}]},
        +  {rand,5000,
        +        [{{rand,uniform_s,2},1000},
        +         {{rand,uniform,1},1000},
        +         {{rand,seed_put,1},1000},
        +         {{rand,seed_get,0},1000},
        +         {{rand,exsss_uniform,2},1000}]},
        +  {erlang,1004,
        +          [{{erlang,put,2},1000},
        +           {{erlang,trace_pattern,3},2},
        +           {{erlang,ensure_tracer_module_loaded,2},2}]},
        +  {sort,1001,[{{sort,do,2},1001}]},
        +  {erts_internal,2,[{{erts_internal,trace_pattern,3},2}]}]}
        +5> cprof:stop().
         12625

        The example shows some details of how lists:sort/1 works. It used 6173 function calls in module lists to complete the work.

        This time, since the shell was not involved in starting and stopping cprof, no other work was done in the system during the profiling.

        /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/erlang-el.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (898)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/erlang-el.html 2026-08-21 04:00:31.849375649 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/erlang-el.html 2026-08-21 04:00:31.849375649 +0000 @@ -133,23 +133,23 @@ with almost the same argument as the preceding.

      Edit - Alignment

      • C-c C-a (align-current) - aligns comments, arrows, assignments, and type annotations around the cursor.
      Example:
       
      -sum(L) -> sum(L, 0).
      -sum([H|T], Sum) -> sum(T, Sum + H);  % recurse
      -sum([], Sum) -> Sum.   % base case
      +sum(L) -> sum(L, 0).
      +sum([H|T], Sum) -> sum(T, Sum + H);  % recurse
      +sum([], Sum) -> Sum.   % base case
       
      --record { two :: int(), % hello
      -          three = hello :: string(),    % there
      -          four = 42 :: int() }.
      +-record { two :: int(), % hello
      +          three = hello :: string(),    % there
      +          four = 42 :: int() }.
       
       becomes:
       
      -sum(L) -> sum(L, 0).
      -sum([H|T], Sum) -> sum(T, Sum + H); % recurse
      -sum([], Sum)    -> Sum.             % base case
      +sum(L) -> sum(L, 0).
      +sum([H|T], Sum) -> sum(T, Sum + H); % recurse
      +sum([], Sum)    -> Sum.             % base case
       
      --record { two           :: int(),    % hello
      -          three = hello :: string(), % there
      -          four  = 42    :: int() }.

      Syntax highlighting

      The syntax highlighting can be activated from the Erlang menu. There are four +-record { two :: int(), % hello + three = hello :: string(), % there + four = 42 :: int() }.

    Syntax highlighting

    The syntax highlighting can be activated from the Erlang menu. There are four different alternatives:

    • Off: Normal black and white display.
    • Level 1: Function headers, reserved words, comments, strings, quoted atoms, and character constants will be colored.
    • Level 2: The above, attributes, Erlang bif:s, guards, and words in comments enclosed in single quotes will be colored.
    • Level 3: The above, variables, records, and macros will be colored. (This /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/fprof.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1176)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/fprof.html 2026-08-21 04:00:31.880375851 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/fprof.html 2026-08-21 04:00:31.880375851 +0000 @@ -134,61 +134,61 @@ interested reader to try it out. Note that some flags to analyse/1 will affect the format.

      The following example was run on Erlang/OTP R8 on Solaris 8; all OTP internals in this example are version dependent.

      As an example, we will use the following function, which is a -slightly modified benchmark function from module file:

      -module(foo).
      --export([create_file_slow/2]).
      +slightly modified benchmark function from module file:

      -module(foo).
      +-export([create_file_slow/2]).
       
      -create_file_slow(Name, N) when is_integer(N), N >= 0 ->
      -    {ok, FD} =
      -        file:open(Name, [raw, write, delayed_write, binary]),
      +create_file_slow(Name, N) when is_integer(N), N >= 0 ->
      +    {ok, FD} =
      +        file:open(Name, [raw, write, delayed_write, binary]),
           if N > 256 ->
      -            ok = file:write(FD,
      -                            lists:map(fun (X) -> <<X:32/unsigned>> end,
      -                            lists:seq(0, 255))),
      -            ok = create_file_slow(FD, 256, N);
      +            ok = file:write(FD,
      +                            lists:map(fun (X) -> <<X:32/unsigned>> end,
      +                            lists:seq(0, 255))),
      +            ok = create_file_slow(FD, 256, N);
              true ->
      -            ok = create_file_slow(FD, 0, N)
      +            ok = create_file_slow(FD, 0, N)
           end,
      -    ok = file:close(FD).
      +    ok = file:close(FD).
       
      -create_file_slow(FD, M, M) ->
      +create_file_slow(FD, M, M) ->
           ok;
      -create_file_slow(FD, M, N) ->
      -    ok = file:write(FD, <<M:32/unsigned>>),
      -    create_file_slow(FD, M+1, N).

      Let us have a look at the printout after running:

      1> fprof:apply(foo, create_file_slow, [junk, 1024]).
      -2> fprof:profile().
      -3> fprof:analyse().

      The printout starts with:

      %% Analysis results:
      -{  analysis_options,
      - [{callers, true},
      -  {sort, acc},
      -  {totals, false},
      -  {details, true}]}.
      +create_file_slow(FD, M, N) ->
      +    ok = file:write(FD, <<M:32/unsigned>>),
      +    create_file_slow(FD, M+1, N).

      Let us have a look at the printout after running:

      1> fprof:apply(foo, create_file_slow, [junk, 1024]).
      +2> fprof:profile().
      +3> fprof:analyse().

      The printout starts with:

      %% Analysis results:
      +{  analysis_options,
      + [{callers, true},
      +  {sort, acc},
      +  {totals, false},
      +  {details, true}]}.
       
       %                                       CNT       ACC       OWN
      -[{ totals,                             9627, 1691.119, 1659.074}].  %%%

      The CNT column shows the total number of function calls that was found in the +[{ totals, 9627, 1691.119, 1659.074}]. %%%

      The CNT column shows the total number of function calls that was found in the trace. In the ACC column is the total time of the trace from first timestamp to last. And in the OWN column is the sum of the execution time in functions found in the trace, not including called functions. In this case it is very close to the ACC time since the emulator had practically nothing to do except executing our test program.

      All time values in the printout are in milliseconds.

      The printout continues:

      %                                       CNT       ACC       OWN
      -[{ "<0.28.0>",                         9627,undefined, 1659.074}].   %%

      This is the printout header of one process. The printout contains only this one +[{ "<0.28.0>", 9627,undefined, 1659.074}]. %%

    This is the printout header of one process. The printout contains only this one process since we called fprof:apply/3 that traces only the current process. Therefore the CNT and OWN columns perfectly matches the totals above. The ACC column is undefined since summing the ACC times of all calls in the process makes no sense — one would get something like the ACC value from totals above multiplied by the average depth of the call stack.

    All paragraphs up to the next process header only concerns function calls within -this process.

    Now we come to something more interesting:

    {[{undefined,                             0, 1691.076,    0.030}],
    - { {fprof,apply_start_stop,4},            0, 1691.076,    0.030},     %
    - [{{foo,create_file_slow,2},              1, 1691.046,    0.103},
    -  {suspend,                               1,    0.000,    0.000}]}.
    +this process.

    Now we come to something more interesting:

    {[{undefined,                             0, 1691.076,    0.030}],
    + { {fprof,apply_start_stop,4},            0, 1691.076,    0.030},     %
    + [{{foo,create_file_slow,2},              1, 1691.046,    0.103},
    +  {suspend,                               1,    0.000,    0.000}]}.
     
    -{[{{fprof,apply_start_stop,4},            1, 1691.046,    0.103}],
    - { {foo,create_file_slow,2},              1, 1691.046,    0.103},     %
    - [{{file,close,1},                        1, 1398.873,    0.019},
    -  {{foo,create_file_slow,3},              1,  249.678,    0.029},
    -  {{file,open,2},                         1,   20.778,    0.055},
    -  {{lists,map,2},                         1,   16.590,    0.043},
    -  {{lists,seq,2},                         1,    4.708,    0.017},
    -  {{file,write,2},                        1,    0.316,    0.021}]}.

    The printout consists of one paragraph per called function. The function +{[{{fprof,apply_start_stop,4}, 1, 1691.046, 0.103}], + { {foo,create_file_slow,2}, 1, 1691.046, 0.103}, % + [{{file,close,1}, 1, 1398.873, 0.019}, + {{foo,create_file_slow,3}, 1, 249.678, 0.029}, + {{file,open,2}, 1, 20.778, 0.055}, + {{lists,map,2}, 1, 16.590, 0.043}, + {{lists,seq,2}, 1, 4.708, 0.017}, + {{file,write,2}, 1, 0.316, 0.021}]}.

    The printout consists of one paragraph per called function. The function marked with % is the one the paragraph concerns — foo:create_file_slow/2. Above the marked function are the calling functions — those that has called the marked, and below are those called by the marked function.

    The paragraphs are per default sorted in descending order of the ACC column for @@ -205,12 +205,12 @@ (lists:seq/2 and lists:map/2).

    The function undefined that has called fprof:apply_start_stop/4 is an unknown function because that call was not recorded in the trace. It was only recorded that the execution returned from fprof:apply_start_stop/4 to some -other function above in the call stack, or that the process exited from there.

    Let us continue down the printout to find:

    {[{{foo,create_file_slow,2},              1,  249.678,    0.029},
    -  {{foo,create_file_slow,3},            768,    0.000,   23.294}],
    - { {foo,create_file_slow,3},            769,  249.678,   23.323},     %
    - [{{file,write,2},                      768,  220.314,   14.539},
    -  {suspend,                              57,    6.041,    0.000},
    -  {{foo,create_file_slow,3},            768,    0.000,   23.294}]}.

    If you compare with the code you will see there also that +other function above in the call stack, or that the process exited from there.

    Let us continue down the printout to find:

    {[{{foo,create_file_slow,2},              1,  249.678,    0.029},
    +  {{foo,create_file_slow,3},            768,    0.000,   23.294}],
    + { {foo,create_file_slow,3},            769,  249.678,   23.323},     %
    + [{{file,write,2},                      768,  220.314,   14.539},
    +  {suspend,                              57,    6.041,    0.000},
    +  {{foo,create_file_slow,3},            768,    0.000,   23.294}]}.

    If you compare with the code you will see there also that foo:create_file_slow/3 was called only from foo:create_file_slow/2 and itself, and called only file:write/2, note the number of calls to file:write/2. But here we see that suspend was called a few times. This is a @@ -218,88 +218,88 @@ foo:create_file_slow/3, and since there is no receive or erlang:yield/0 in the code, it must be Erlang scheduling suspensions, or the trace file driver compensating for large file write operations (these are regarded as a schedule -out followed by a schedule in to the same process).

    Let us find the suspend entry:

    {[{{file,write,2},                       53,    6.281,    0.000},
    -  {{foo,create_file_slow,3},             57,    6.041,    0.000},
    -  {{prim_file,drv_command,4},            50,    4.582,    0.000},
    -  {{prim_file,drv_get_response,1},       34,    2.986,    0.000},
    -  {{lists,map,2},                        10,    2.104,    0.000},
    -  {{prim_file,write,2},                  17,    1.852,    0.000},
    -  {{erlang,port_command,2},              15,    1.713,    0.000},
    -  {{prim_file,drv_command,2},            22,    1.482,    0.000},
    -  {{prim_file,translate_response,2},     11,    1.441,    0.000},
    -  {{prim_file,'-drv_command/2-fun-0-',1},  15,    1.340,    0.000},
    -  {{lists,seq,4},                         3,    0.880,    0.000},
    -  {{foo,'-create_file_slow/2-fun-0-',1},   5,    0.523,    0.000},
    -  {{erlang,bump_reductions,1},            4,    0.503,    0.000},
    -  {{prim_file,open_int_setopts,3},        1,    0.165,    0.000},
    -  {{prim_file,i32,4},                     1,    0.109,    0.000},
    -  {{fprof,apply_start_stop,4},            1,    0.000,    0.000}],
    - { suspend,                             299,   32.002,    0.000},     %
    - [ ]}.

    We find no particularly long suspend times, so no function seems to have waited +out followed by a schedule in to the same process).

    Let us find the suspend entry:

    {[{{file,write,2},                       53,    6.281,    0.000},
    +  {{foo,create_file_slow,3},             57,    6.041,    0.000},
    +  {{prim_file,drv_command,4},            50,    4.582,    0.000},
    +  {{prim_file,drv_get_response,1},       34,    2.986,    0.000},
    +  {{lists,map,2},                        10,    2.104,    0.000},
    +  {{prim_file,write,2},                  17,    1.852,    0.000},
    +  {{erlang,port_command,2},              15,    1.713,    0.000},
    +  {{prim_file,drv_command,2},            22,    1.482,    0.000},
    +  {{prim_file,translate_response,2},     11,    1.441,    0.000},
    +  {{prim_file,'-drv_command/2-fun-0-',1},  15,    1.340,    0.000},
    +  {{lists,seq,4},                         3,    0.880,    0.000},
    +  {{foo,'-create_file_slow/2-fun-0-',1},   5,    0.523,    0.000},
    +  {{erlang,bump_reductions,1},            4,    0.503,    0.000},
    +  {{prim_file,open_int_setopts,3},        1,    0.165,    0.000},
    +  {{prim_file,i32,4},                     1,    0.109,    0.000},
    +  {{fprof,apply_start_stop,4},            1,    0.000,    0.000}],
    + { suspend,                             299,   32.002,    0.000},     %
    + [ ]}.

    We find no particularly long suspend times, so no function seems to have waited in a receive statement. Actually, prim_file:drv_command/4 contains a receive statement, but in this test program, the message lies in the process receive buffer when the receive statement is entered. We also see that the total suspend time for the test run is small.

    The suspend pseudo function has an OWN time of zero. This is to prevent the process total OWN time from including time in suspension. Whether suspend -time is really ACC or OWN time is more of a philosophical question.

    Now we look at another interesting pseudo function, garbage_collect:

    {[{{prim_file,drv_command,4},            25,    0.873,    0.873},
    -  {{prim_file,write,2},                  16,    0.692,    0.692},
    -  {{lists,map,2},                         2,    0.195,    0.195}],
    - { garbage_collect,                      43,    1.760,    1.760},     %
    - [ ]}.

    Here we see that no function stands out, which is very normal.

    The garbage_collect pseudo function has not an OWN time of zero like +time is really ACC or OWN time is more of a philosophical question.

    Now we look at another interesting pseudo function, garbage_collect:

    {[{{prim_file,drv_command,4},            25,    0.873,    0.873},
    +  {{prim_file,write,2},                  16,    0.692,    0.692},
    +  {{lists,map,2},                         2,    0.195,    0.195}],
    + { garbage_collect,                      43,    1.760,    1.760},     %
    + [ ]}.

    Here we see that no function stands out, which is very normal.

    The garbage_collect pseudo function has not an OWN time of zero like suspend, instead it is equal to the ACC time.

    Garbage collection often occurs while a process is suspended, but fprof hides this fact by pretending that the suspended function was first unsuspended and then garbage collected. Otherwise the printout would show garbage_collect being called from suspend, but not which function that might have caused the -garbage collection.

    Let us now get back to the test code:

    {[{{foo,create_file_slow,3},            768,  220.314,   14.539},
    -  {{foo,create_file_slow,2},              1,    0.316,    0.021}],
    - { {file,write,2},                      769,  220.630,   14.560},     %
    - [{{prim_file,write,2},                 769,  199.789,   22.573},
    -  {suspend,                              53,    6.281,    0.000}]}.

    Not unexpectedly, we see that file:write/2 was called from +garbage collection.

    Let us now get back to the test code:

    {[{{foo,create_file_slow,3},            768,  220.314,   14.539},
    +  {{foo,create_file_slow,2},              1,    0.316,    0.021}],
    + { {file,write,2},                      769,  220.630,   14.560},     %
    + [{{prim_file,write,2},                 769,  199.789,   22.573},
    +  {suspend,                              53,    6.281,    0.000}]}.

    Not unexpectedly, we see that file:write/2 was called from foo:create_file_slow/3 and foo:create_file_slow/2. The number of calls in each case as well as the used time are also confirms the previous results.

    We see that file:write/2 only calls prim_file:write/2, but let us refrain from digging into the internals of the kernel application.

    If we nevertheless do dig down we find the call to the linked-in driver -that does the file operations towards the host operating system:

    {[{{prim_file,drv_command,4},           772, 1458.356, 1456.643}],
    - { {erlang,port_command,2},             772, 1458.356, 1456.643},     %
    - [{suspend,                              15,    1.713,    0.000}]}.

    This is 86 % of the total run time, and as we saw before it is the close +that does the file operations towards the host operating system:

    {[{{prim_file,drv_command,4},           772, 1458.356, 1456.643}],
    + { {erlang,port_command,2},             772, 1458.356, 1456.643},     %
    + [{suspend,                              15,    1.713,    0.000}]}.

    This is 86 % of the total run time, and as we saw before it is the close operation the absolutely biggest contributor. We find a comparison ratio a -little bit up in the call stack:

    {[{{prim_file,close,1},                   1, 1398.748,    0.024},
    -  {{prim_file,write,2},                 769,  174.672,   12.810},
    /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/fprof_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737))
    --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/fprof_chapter.html	2026-08-21 04:00:31.898375968 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/fprof_chapter.html	2026-08-21 04:00:31.899375974 +0000
    @@ -122,10 +122,10 @@
     The tracing has to be stopped at a suitable later time using
     fprof:trace(stop).

    Immediate profiling

    It is also possible to trace immediately into the profiling process that creates the raw profile data, that is to short circuit the tracing and profiling steps -so that the filesystem is not used for tracing.

    Do something like this:

    {ok, Tracer} = fprof:profile(start),
    -fprof:trace([start, {tracer, Tracer}]),
    +so that the filesystem is not used for tracing.

    Do something like this:

    {ok, Tracer} = fprof:profile(start),
    +fprof:trace([start, {tracer, Tracer}]),
     %% Run code to profile
    -fprof:trace(stop);

    This puts less load on the filesystem, but much more load on the Erlang runtime +fprof:trace(stop);

    This puts less load on the filesystem, but much more load on the Erlang runtime system.

    /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/lcnt_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2084)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/lcnt_chapter.html 2026-08-21 04:00:31.917376092 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/lcnt_chapter.html 2026-08-21 04:00:31.916376085 +0000 @@ -173,20 +173,20 @@ <nonode@nohost.189.0> 5354 0.5230 118 <nonode@nohost.121.0> 5845 0.9239 115 <nonode@nohost.104.0> 5140 0.7782 108 -ok

    Example with Mnesia Transaction Benchmark

    From the Erlang shell:

    Erlang/OTP 27 [erts-15.0] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [lock-counting]
    +ok

    Example with Mnesia Transaction Benchmark

    From the Erlang shell:

    Erlang/OTP 27 [erts-15.0] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [lock-counting]
     
    -Eshell V15.0 (press Ctrl+G to abort, type help(). for help)
    -1> Conf = [{db_nodes, [node()]}, {driver_nodes, [node()]}, {replica_nodes, [node()]},
    -    {n_drivers_per_node, 10}, {n_branches, 1000}, {n_accounts_per_branch, 10},
    -    {replica_type, ram_copies}, {stop_after, 60000}, {reuse_history_id, true}], ok.
    +Eshell V15.0 (press Ctrl+G to abort, type help(). for help)
    +1> Conf = [{db_nodes, [node()]}, {driver_nodes, [node()]}, {replica_nodes, [node()]},
    +    {n_drivers_per_node, 10}, {n_branches, 1000}, {n_accounts_per_branch, 10},
    +    {replica_type, ram_copies}, {stop_after, 60000}, {reuse_history_id, true}], ok.
     ok
    -2> mnesia_tpcb:init([{use_running_mnesia, false}|Conf]).
    +2> mnesia_tpcb:init([{use_running_mnesia, false}|Conf]).
         .
         .
         .
     ignore

    Initial configuring of the benchmark is done. It is time to profile the actual -Mnesia benchmark:

    3> lcnt:apply(fun() -> {ok,{time, Tps,_,_,_,_}} = mnesia_tpcb:run([{use_running_mnesia,
    -    true}|Conf]), Tps/60 end).
    +Mnesia benchmark:

    3> lcnt:apply(fun() -> {ok,{time, Tps,_,_,_,_}} = mnesia_tpcb:run([{use_running_mnesia,
    +    true}|Conf]), Tps/60 end).
           .
           .
           .
    @@ -278,63 +278,63 @@
     However, one should also look for high lock acquisition frequencies (#tries)
     since locks generate overhead and because high frequency could become
     problematic if they begin to have conflicts even if it is not shown in a
    -particular test.

    The Big Bang Benchmark

    -module(big).
    --export([bang/1]).
    +particular test.

    The Big Bang Benchmark

    -module(big).
    +-export([bang/1]).
     
    -pinger([], [], true) ->
    +pinger([], [], true) ->
         receive
    -	{procs, Procs, ReportTo} ->
    -	    pinger(Procs, [], ReportTo)
    +	{procs, Procs, ReportTo} ->
    +	    pinger(Procs, [], ReportTo)
         end;
    -pinger([], [], false) ->
    -    receive {ping, From} -> From ! {pong, self()} end,
    -    pinger([],[],false);
    -pinger([], [], ReportTo) ->
    -    ReportTo ! {done, self()},
    -    pinger([],[],false);
    -pinger([], [Po|Pos] = Pongers, ReportTo) ->
    +pinger([], [], false) ->
    +    receive {ping, From} -> From ! {pong, self()} end,
    +    pinger([],[],false);
    +pinger([], [], ReportTo) ->
    +    ReportTo ! {done, self()},
    +    pinger([],[],false);
    +pinger([], [Po|Pos] = Pongers, ReportTo) ->
         receive
    -	{ping, From} ->
    -	    From ! {pong, self()},
    -	    pinger([], Pongers, ReportTo);
    -	{pong, Po} ->
    -	    pinger([], Pos, ReportTo)
    +	{ping, From} ->
    +	    From ! {pong, self()},
    +	    pinger([], Pongers, ReportTo);
    +	{pong, Po} ->
    +	    pinger([], Pos, ReportTo)
         end;
    -pinger([Pi|Pis], Pongers, ReportTo) ->
    -    receive {ping, From} -> From ! {pong, self()}
    +pinger([Pi|Pis], Pongers, ReportTo) ->
    +    receive {ping, From} -> From ! {pong, self()}
         after 0 -> ok
         end,
    -    Pi ! {ping, self()},
    -    pinger(Pis, [Pi|Pongers], ReportTo).
    +    Pi ! {ping, self()},
    +    pinger(Pis, [Pi|Pongers], ReportTo).
     
    -spawn_procs(N) when N =< 0 ->
    -    [];
    -spawn_procs(N) ->
    -    [spawn_link(fun () -> pinger([],[],true) end) | spawn_procs(N-1)].
    +spawn_procs(N) when N =< 0 ->
    +    [];
    +spawn_procs(N) ->
    +    [spawn_link(fun () -> pinger([],[],true) end) | spawn_procs(N-1)].
     
    -send_procs([], Msg) ->
    +send_procs([], Msg) ->
         Msg;
    -send_procs([P|Ps], Msg) ->
    +send_procs([P|Ps], Msg) ->
         P ! Msg,
    -    send_procs(Ps, Msg).
    +    send_procs(Ps, Msg).
     
    -receive_msgs([]) ->
    +receive_msgs([]) ->
         ok;
    -receive_msgs([M|Ms]) ->
    +receive_msgs([M|Ms]) ->
         receive
     	M ->
    -	    receive_msgs(Ms)
    +	    receive_msgs(Ms)
         end.
     
    -bang(N) when integer(N) ->
    -    Procs = spawn_procs(N),
    -    RMsgs = lists:map(fun (P) -> {done, P} end, Procs),
    -    Start = now(),
    -    send_procs(Procs, {procs, Procs, self()}),
    -    receive_msgs(RMsgs),
    -    Stop = now(),
    -    lists:foreach(fun (P) -> exit(P, normal) end, Procs),
    -    timer:now_diff(Stop, Start).

    See Also

    LCNT Reference Manual

    +
    bang(N) when integer(N) -> + Procs = spawn_procs(N), + RMsgs = lists:map(fun (P) -> {done, P} end, Procs), + Start = now(), + send_procs(Procs, {procs, Procs, self()}), + receive_msgs(RMsgs), + Stop = now(), + lists:foreach(fun (P) -> exit(P, normal) end, Procs), + timer:now_diff(Stop, Start).

    See Also

    LCNT Reference Manual

    /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/make.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (793)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/make.html 2026-08-21 04:00:31.935376209 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/make.html 2026-08-21 04:00:31.935376209 +0000 @@ -101,8 +101,8 @@ the first match is used. For example, the following Emakefile means that file1 should be compiled with the options [debug_info,{i,"../foo"}], while all other files in the current directory should be compiled with only the -debug_info flag.

    {'file1',[debug_info,{i,"../foo"}]}.
    -{'*',[debug_info]}.

    See Also

    The Compiler Application

    +debug_info flag.

    {'file1',[debug_info,{i,"../foo"}]}.
    +{'*',[debug_info]}.

    See Also

    The Compiler Application

    /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/notes.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (9966)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/notes.html 2026-08-21 04:00:31.966376410 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/notes.html 2026-08-21 04:00:31.966376410 +0000 @@ -89,37 +89,37 @@ -

    This document describes the changes made to the Tools application.

    Tools 4.1.4

    Improvements and New Features

    • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

      A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

      make release_docs places the documentation in the released code under the doc folder.

      make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

      The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

      Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

      Improves the source Software-Bill-of-Materials

      • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
      • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
      • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

      Own Id: OTP-19886 Aux Id: PR-10434

    Tools 4.1.3

    Improvements and New Features

    • Fixed some deprecations for newer emacs versions.

      Own Id: OTP-19726 Aux Id: PR-10106

    Tools 4.1.2

    Fixed Bugs and Malfunctions

    • A crash has been eliminated in tprof:collect/0 when unloading a module while collecting traces.

      Own Id: OTP-19135 Aux Id: GH-8483, PR-8547

    • Improved the indent-region Emacs command, which could indent badly when inside multiline string.

      Own Id: OTP-19396 Aux Id: PR-9186

    • eprof:start_profiling/3 can now return information about which process it failed to trace.

      Own Id: OTP-19419 Aux Id: PR-9219

    • Fixed a race condition when processes cause the Cover server to be started at the same time.

      Own Id: OTP-19517 Aux Id: PR-9124

    • Fix bug in tprof where the session name could not be set.

      Own Id: OTP-19580 Aux Id: PR-9648

    • Add tprof to the .app file.

      Own Id: OTP-19628 Aux Id: PR-9787

    Improvements and New Features

    • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

      Own Id: OTP-19575 Aux Id: PR-9670

    Tools 4.1.1

    Fixed Bugs and Malfunctions

    • Fixed some deprecated errors on emacs-29.

      Own Id: OTP-19273 Aux Id: PR-8879

    • The cover tool could sometimes wrongly report lines as uncovered.

      Own Id: OTP-19289 Aux Id: GH-8867, PR-8919

    • Fixed tprof:format(IoDevice, ...) to not demand unicode encoding supported by IoDevice.

      Own Id: OTP-19299 Aux Id: PR-8949

    Tools 4.1

    Fixed Bugs and Malfunctions

    • tprof no longer crashes when using pause/restart/continue when profiling all modules.

      Own Id: OTP-19136 Aux Id: GH-8472, PR-8472, PR-8541

    • On systems supporting native coverage, calls to cover could hang or crash if cover-compiled module had been reloaded from outside cover. This has been corrected so that cover now recovers from the error and and sends a report to the logger about the failure to retrieve coverage information.

      Own Id: OTP-19203 Aux Id: GH-8661, PR-8742

    Improvements and New Features

    • Figures in the documentation have been improved.

      Own Id: OTP-19130 Aux Id: PR-7226

    Tools 4.0

    Fixed Bugs and Malfunctions

    • Dialyzer warnings due to type specs added in dbg have been eliminated.

      Own Id: OTP-18860

    • In Erlang/OTP 26, doing a cover analysis on the line level would return multiple entries for lines on which multiple functions were defined.

      For example, consider this module:

      -module(foo).
      --export([bar/0, baz/0]).
      +

      This document describes the changes made to the Tools application.

      Tools 4.1.4

      Improvements and New Features

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      Tools 4.1.3

      Improvements and New Features

      • Fixed some deprecations for newer emacs versions.

        Own Id: OTP-19726 Aux Id: PR-10106

      Tools 4.1.2

      Fixed Bugs and Malfunctions

      • A crash has been eliminated in tprof:collect/0 when unloading a module while collecting traces.

        Own Id: OTP-19135 Aux Id: GH-8483, PR-8547

      • Improved the indent-region Emacs command, which could indent badly when inside multiline string.

        Own Id: OTP-19396 Aux Id: PR-9186

      • eprof:start_profiling/3 can now return information about which process it failed to trace.

        Own Id: OTP-19419 Aux Id: PR-9219

      • Fixed a race condition when processes cause the Cover server to be started at the same time.

        Own Id: OTP-19517 Aux Id: PR-9124

      • Fix bug in tprof where the session name could not be set.

        Own Id: OTP-19580 Aux Id: PR-9648

      • Add tprof to the .app file.

        Own Id: OTP-19628 Aux Id: PR-9787

      Improvements and New Features

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      Tools 4.1.1

      Fixed Bugs and Malfunctions

      • Fixed some deprecated errors on emacs-29.

        Own Id: OTP-19273 Aux Id: PR-8879

      • The cover tool could sometimes wrongly report lines as uncovered.

        Own Id: OTP-19289 Aux Id: GH-8867, PR-8919

      • Fixed tprof:format(IoDevice, ...) to not demand unicode encoding supported by IoDevice.

        Own Id: OTP-19299 Aux Id: PR-8949

      Tools 4.1

      Fixed Bugs and Malfunctions

      • tprof no longer crashes when using pause/restart/continue when profiling all modules.

        Own Id: OTP-19136 Aux Id: GH-8472, PR-8472, PR-8541

      • On systems supporting native coverage, calls to cover could hang or crash if cover-compiled module had been reloaded from outside cover. This has been corrected so that cover now recovers from the error and and sends a report to the logger about the failure to retrieve coverage information.

        Own Id: OTP-19203 Aux Id: GH-8661, PR-8742

      Improvements and New Features

      • Figures in the documentation have been improved.

        Own Id: OTP-19130 Aux Id: PR-7226

      Tools 4.0

      Fixed Bugs and Malfunctions

      • Dialyzer warnings due to type specs added in dbg have been eliminated.

        Own Id: OTP-18860

      • In Erlang/OTP 26, doing a cover analysis on the line level would return multiple entries for lines on which multiple functions were defined.

        For example, consider this module:

        -module(foo).
        +-export([bar/0, baz/0]).
         
        -bar() -> ok. baz() -> not_ok.

        In Erlang/OTP 26, analysing on the line level would return two entries -for line 4:

        1> cover:compile_module(foo).
        -{ok,foo}
        -2> foo:bar().
        +bar() -> ok. baz() -> not_ok.

        In Erlang/OTP 26, analysing on the line level would return two entries +for line 4:

        1> cover:compile_module(foo).
        +{ok,foo}
        +2> foo:bar().
         ok
        -3> cover:analyse(foo, coverage, line).
        -{ok,[{{foo,4},{1,0}},{{foo,4},{0,1}}]}
        -4> cover:analyse(foo, calls, line).
        -{ok,[{{foo,4},1},{{foo,4},0}]}

        In Erlang/OTP 27, there will only be a single entry for line 4:

        1> cover:compile_module(foo).
        -{ok,foo}
        -2> foo:bar().
        +3> cover:analyse(foo, coverage, line).
        +{ok,[{{foo,4},{1,0}},{{foo,4},{0,1}}]}
        +4> cover:analyse(foo, calls, line).
        +{ok,[{{foo,4},1},{{foo,4},0}]}

        In Erlang/OTP 27, there will only be a single entry for line 4:

        1> cover:compile_module(foo).
        +{ok,foo}
        +2> foo:bar().
         ok
        -3> cover:analyse(foo, coverage, line).
        -{ok,[{{foo,4},{1,0}}]}
        -4> cover:analyse(foo, calls, line).
        -{ok,[{{foo,4},1}]}

        Own Id: OTP-18998 Aux Id: GH-8159, PR-8182

      • Fixed align command in emacs mode.

        Own Id: OTP-19026 Aux Id: PR-8155

      Improvements and New Features

      • Triple-Quoted Strings has been implemented as per EEP 64. See String in the Reference Manual.

        Example:

        1> """
        +3> cover:analyse(foo, coverage, line).
        +{ok,[{{foo,4},{1,0}}]}
        +4> cover:analyse(foo, calls, line).
        +{ok,[{{foo,4},1}]}

        Own Id: OTP-18998 Aux Id: GH-8159, PR-8182

      • Fixed align command in emacs mode.

        Own Id: OTP-19026 Aux Id: PR-8155

      Improvements and New Features

      • Triple-Quoted Strings has been implemented as per EEP 64. See String in the Reference Manual.

        Example:

        1> """
            a
            b
            c
            """.
         "a\nb\nc"

        Adjacent string literals without intervening white space is now a syntax error, to avoid possible confusion with triple-quoted strings. For example:

        1> "abc""xyz".
         "xyz".
        -* 1:6: adjacent string literals without intervening white space

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-18750 Aux Id: OTP-18746, PR-7313, PR-7451

      • There is a new tool tprof, which combines the functionality of eprof and cprof under one interface and adds heap profiling. It also has functionality to help with profiling process hierarchies.

        Example:

        1> tprof:profile(lists, seq, [1, 16], #href_anchor"ss">type => call_memory}).
        +* 1:6: adjacent string literals without intervening white space

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-18750 Aux Id: OTP-18746, PR-7313, PR-7451

      • There is a new tool tprof, which combines the functionality of eprof and cprof under one interface and adds heap profiling. It also has functionality to help with profiling process hierarchies.

        Example:

        1> tprof:profile(lists, seq, [1, 16], #href_anchor"ss">type => call_memory}).
         
         ****** Process <0.92.0>  --  100.00% of total *** 
        -FUNCTION          CALLS  WORDS  PER CALL  [     %]
        -lists:seq_loop/3      5     32      6.40  [100.00]
        -                            32            [ 100.0]
        +FUNCTION          CALLS  WORDS  PER CALL  [     %]
        +lists:seq_loop/3      5     32      6.40  [100.00]
        +                            32            [ 100.0]
         ok

        Own Id: OTP-18756 Aux Id: PR-6639

      • Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code.

        There are also new APIs to support native coverage without using the cover tool.

        To instrument code for native coverage it must be compiled with the line_coverage option.

        To enable native coverage in the runtime system, start it like so:

        $ erl +JPcover true

        There are also the following new functions for supporting native coverage:

        Own Id: OTP-18856 Aux Id: PR-7856

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      • Improved the align command in emacs mode.

        Own Id: OTP-19080 Aux Id: PR-8288

      Tools 3.6

      Improvements and New Features

      • Map comprehensions as suggested in EEP 58 has now been implemented.

        Own Id: OTP-18413 Aux Id: EEP-58, PR-6727

      • The instrument module has been moved from tools to runtime_tools.

        Own Id: OTP-18487 Aux Id: PR-6829

      Tools 3.5.3

      Improvements and New Features

      • Removed the previously undocumented and unsupported emem tool.

        Own Id: OTP-17892 Aux Id: PR-5591

      Tools 3.5.2

      Fixed Bugs and Malfunctions

      • Erlang-mode fixed for newer versions of xref using CL-Lib structures instead of EIEIO classes.

        Own Id: OTP-17746 Aux Id: GH-5314, PR-5324

      Tools 3.5.1

      Fixed Bugs and Malfunctions

      • The cover tool would not work on modules compiled with the tuple_calls option.

        Own Id: OTP-17440 Aux Id: GH-4796

      Tools 3.5

      Fixed Bugs and Malfunctions

      • For cover-compiled code, the error behaviour of list and binary comprehensions /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> tools - 4.1.4 - urn:uuid:4bd7995f-d6b0-c022-040c-3ef7757fd8b2 + urn:uuid:f680b153-0140-f4d4-149d-e3889de1ff3d en - 2026-08-21T03:47:41Z + 2042-09-22T17:06:20Z /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/cover_chapter.xhtml differs (HTML document, ASCII text, with very long lines (893)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/cover_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/cover_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -20,75 +20,75 @@

        Introduction

        The module cover provides a set of functions for coverage analysis of Erlang programs, counting how many times each executable line is executed.

        Coverage analysis can be used to verify test cases, making sure all relevant -code is covered, and can be helpful when looking for bottlenecks in the code.

        Getting Started With Cover

        Example

        Assume that a test case for the following program should be verified:

        -module(channel).
        --behaviour(gen_server).
        +code is covered, and can be helpful when looking for bottlenecks in the code.

        Getting Started With Cover

        Example

        Assume that a test case for the following program should be verified:

        -module(channel).
        +-behaviour(gen_server).
         
        --export([start_link/0,stop/0]).
        --export([alloc/0,free/1]). % client interface
        --export([init/1,handle_call/3,terminate/2]). % callback functions
        +-export([start_link/0,stop/0]).
        +-export([alloc/0,free/1]). % client interface
        +-export([init/1,handle_call/3,terminate/2]). % callback functions
         
        -start_link() ->
        -    gen_server:start_link({local,channel}, channel, [], []).
        +start_link() ->
        +    gen_server:start_link({local,channel}, channel, [], []).
         
        -stop() ->
        -    gen_server:call(channel, stop).
        +stop() ->
        +    gen_server:call(channel, stop).
         
         %%%-Client interface functions-------------------------------------------
         
        -alloc() ->
        -    gen_server:call(channel, alloc).
        +alloc() ->
        +    gen_server:call(channel, alloc).
         
        -free(Channel) ->
        -    gen_server:call(channel, {free,Channel}).
        +free(Channel) ->
        +    gen_server:call(channel, {free,Channel}).
         
         %%%-gen_server callback functions----------------------------------------
         
        -init(_Arg) ->
        -    {ok,channels()}.
        +init(_Arg) ->
        +    {ok,channels()}.
         
        -handle_call(stop, _Client, Channels) ->
        -    {stop,normal,ok,Channels};
        +handle_call(stop, _Client, Channels) ->
        +    {stop,normal,ok,Channels};
         
        -handle_call(alloc, _Client, Channels) ->
        -    {Ch,Channels2} = alloc(Channels),
        -    {reply,{ok,Ch},Channels2};
        +handle_call(alloc, _Client, Channels) ->
        +    {Ch,Channels2} = alloc(Channels),
        +    {reply,{ok,Ch},Channels2};
         
        -handle_call({free,Channel}, _Client, Channels) ->
        -    Channels2 = free(Channel, Channels),
        -    {reply,ok,Channels2}.
        +handle_call({free,Channel}, _Client, Channels) ->
        +    Channels2 = free(Channel, Channels),
        +    {reply,ok,Channels2}.
         
        -terminate(_Reason, _Channels) ->
        +terminate(_Reason, _Channels) ->
             ok.
         
         %%%-Internal functions---------------------------------------------------
         
        -channels() ->
        -    [ch1,ch2,ch3].
        +channels() ->
        +    [ch1,ch2,ch3].
         
        -alloc([Channel|Channels]) ->
        -    {Channel,Channels};
        -alloc([]) ->
        +alloc([Channel|Channels]) ->
        +    {Channel,Channels};
        +alloc([]) ->
             false.
         
        -free(Channel, Channels) ->
        -    [Channel|Channels].

        The test case is implemented as follows:

        -module(test).
        --export([s/0]).
        -
        -s() ->
        -    {ok,Pid} = channel:start_link(),
        -    {ok,Ch1} = channel:alloc(),
        -    ok = channel:free(Ch1),
        -    ok = channel:stop().

        Preparation

        First of all, Cover must be started. This spawns a process which owns the Cover -database where all coverage data will be stored.

        1> cover:start().
        -{ok,<0.90.0>}

        To include other nodes in the coverage analysis, use +free(Channel, Channels) -> + [Channel|Channels].

        The test case is implemented as follows:

        -module(test).
        +-export([s/0]).
        +
        +s() ->
        +    {ok,Pid} = channel:start_link(),
        +    {ok,Ch1} = channel:alloc(),
        +    ok = channel:free(Ch1),
        +    ok = channel:stop().

        Preparation

        First of all, Cover must be started. This spawns a process which owns the Cover +database where all coverage data will be stored.

        1> cover:start().
        +{ok,<0.90.0>}

        To include other nodes in the coverage analysis, use cover:start/1. All cover-compiled modules will then be loaded on all nodes, and data from all nodes will be summed up when analysing. For simplicity this example only involves the current node.

        Before any analysis can take place, the involved modules must be cover-compiled. This means that some extra information is added to the module before beging compiled into a binary and loaded. The source file of the module is -not affected and no .beam file is created.

        2> cover:compile_module(channel).
        -{ok,channel}

        Each time a function in the cover-compiled module channel is called, +not affected and no .beam file is created.

        2> cover:compile_module(channel).
        +{ok,channel}

        Each time a function in the cover-compiled module channel is called, information about the call will be added to the Cover database. Run the test case:

        3> test:s().
         ok

        Cover analysis is performed by examining the contents of the Cover database. The @@ -100,174 +100,174 @@ {Cov,NotCov}, where Cov is the number of executable lines that have been executed at least once and NotCov is the number of executable lines that have not been executed.

        If the analysis is made on module level, the result is given for the entire -module as a tuple {Module,{Cov,NotCov}}:

        4> cover:analyse(channel, coverage, module).
        -{ok,{channel,{14,1}}}

        For channel, the result shows that 14 lines in the module are covered but one +module as a tuple {Module,{Cov,NotCov}}:

        4> cover:analyse(channel, coverage, module).
        +{ok,{channel,{14,1}}}

        For channel, the result shows that 14 lines in the module are covered but one line is not covered.

        If the analysis is made on function level, the result is given as a list of tuples {Function,{Cov,NotCov}}, one for each function in the module. A -function is specified by its module name, function name and arity:

        5> cover:analyse(channel, coverage, function).
        -{ok,[{{channel,start_link,0},{1,0}},
        -     {{channel,stop,0},{1,0}},
        -     {{channel,alloc,0},{1,0}},
        -     {{channel,free,1},{1,0}},
        -     {{channel,init,1},{1,0}},
        -     {{channel,handle_call,3},{5,0}},
        -     {{channel,terminate,2},{1,0}},
        -     {{channel,channels,0},{1,0}},
        -     {{channel,alloc,1},{1,1}},
        -     {{channel,free,2},{1,0}}]}

        For channel, the result shows that the uncovered line is in the function +function is specified by its module name, function name and arity:

        5> cover:analyse(channel, coverage, function).
        +{ok,[{{channel,start_link,0},{1,0}},
        +     {{channel,stop,0},{1,0}},
        +     {{channel,alloc,0},{1,0}},
        +     {{channel,free,1},{1,0}},
        +     {{channel,init,1},{1,0}},
        +     {{channel,handle_call,3},{5,0}},
        +     {{channel,terminate,2},{1,0}},
        +     {{channel,channels,0},{1,0}},
        +     {{channel,alloc,1},{1,1}},
        +     {{channel,free,2},{1,0}}]}

        For channel, the result shows that the uncovered line is in the function channel:alloc/1.

        If the analysis is made on clause level, the result is given as a list of tuples {Clause,{Cov,NotCov}}, one for each function clause in the module. A clause is specified by its module name, function name, arity and position within the -function definition:

        6> cover:analyse(channel, coverage, clause).
        -{ok,[{{channel,start_link,0,1},{1,0}},
        -     {{channel,stop,0,1},{1,0}},
        -     {{channel,alloc,0,1},{1,0}},
        -     {{channel,free,1,1},{1,0}},
        -     {{channel,init,1,1},{1,0}},
        -     {{channel,handle_call,3,1},{1,0}},
        -     {{channel,handle_call,3,2},{2,0}},
        -     {{channel,handle_call,3,3},{2,0}},
        -     {{channel,terminate,2,1},{1,0}},
        -     {{channel,channels,0,1},{1,0}},
        -     {{channel,alloc,1,1},{1,0}},
        -     {{channel,alloc,1,2},{0,1}},
        -     {{channel,free,2,1},{1,0}}]}

        For channel, the result shows that the uncovered line is in the second clause +function definition:

        6> cover:analyse(channel, coverage, clause).
        +{ok,[{{channel,start_link,0,1},{1,0}},
        +     {{channel,stop,0,1},{1,0}},
        +     {{channel,alloc,0,1},{1,0}},
        +     {{channel,free,1,1},{1,0}},
        +     {{channel,init,1,1},{1,0}},
        +     {{channel,handle_call,3,1},{1,0}},
        +     {{channel,handle_call,3,2},{2,0}},
        +     {{channel,handle_call,3,3},{2,0}},
        +     {{channel,terminate,2,1},{1,0}},
        +     {{channel,channels,0,1},{1,0}},
        +     {{channel,alloc,1,1},{1,0}},
        +     {{channel,alloc,1,2},{0,1}},
        +     {{channel,free,2,1},{1,0}}]}

        For channel, the result shows that the uncovered line is in the second clause of channel:alloc/1.

        Finally, if the analysis is made on line level, the result is given as a list of tuples {Line,{Cov,NotCov}}, one for each executable line in the source code. A -line is specified by its module name and line number.

        7> cover:analyse(channel, coverage, line).
        -{ok,[{{channel,9},{1,0}},
        -     {{channel,12},{1,0}},
        -     {{channel,17},{1,0}},
        -     {{channel,20},{1,0}},
        -     {{channel,25},{1,0}},
        -     {{channel,28},{1,0}},
        -     {{channel,31},{1,0}},
        -     {{channel,32},{1,0}},
        -     {{channel,35},{1,0}},
        -     {{channel,36},{1,0}},
        -     {{channel,39},{1,0}},
        -     {{channel,44},{1,0}},
        -     {{channel,47},{1,0}},
        -     {{channel,49},{0,1}},
        /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/cover.xhtml differs (HTML document, ASCII text, with very long lines (674))
        --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/cover.xhtml	2026-08-05 05:56:49.000000000 +0000
        +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/cover.xhtml	2026-08-05 05:56:49.000000000 +0000
        @@ -1433,7 +1433,7 @@
         call is equivalent to analyse('_', coverage, Arg).

        Otherwise Arg is assumed to be a module name, and this call is equivalent to analyse(Arg, coverage, function).

        Note

        To analyze a module whose name overlaps with one the values in analysis() or level(), the module -name has to be in a list. For example, to analyze a module named calls:

        cover:analyse([calls]).
        +name has to be in a list. For example, to analyze a module named calls:

        cover:analyse([calls]).
        @@ -1475,7 +1475,7 @@ analyse(Arg1, Arg2, function).

        If Arg2 is one of the values in level(), Arg1 is assumed to be a module and this call is equivalent to analyse(Arg1, coverage, Arg2).

        Note

        To analyze a module whose name overlaps with one of the values in analysis(), the module name needs to be in a -list. For example, to analyze a module named calls:

        cover:analyse([calls], function).
        +list. For example, to analyze a module named calls:

        cover:analyse([calls], function).
        @@ -1584,7 +1584,7 @@ options, this call is equivalent to analyse_to_file('_', Arg).

        Otherwise Arg is assumed to be a module, and this call is equivalent to analyse_to_file(Arg, []).

        Note

        To analyze a module of the name html (which overlaps with an option in analyse_option()), it is necessary to -use cover:analyse_to_file/2:

        cover:analyse_to_file([html], []).
        +use cover:analyse_to_file/2:

        cover:analyse_to_file([html], []).
        /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/cprof_chapter.xhtml differs (HTML document, ASCII text, with very long lines (1636)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/cprof_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/cprof_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -42,110 +42,110 @@ cprof itself; the only way to analyze cprof is by specifying it as a single module to analyse.

        Call count tracing is very lightweight compared to other forms of tracing since no trace message has to be generated. Some measurements indicates performance -degradations in the vicinity of 10 percent.

        The following sections show some examples of profiling with cprof.

        Example: Background work

        From the Erlang shell:

        1> cprof:start(), cprof:pause(). % Stop counters just after start
        +degradations in the vicinity of 10 percent.

        The following sections show some examples of profiling with cprof.

        Example: Background work

        From the Erlang shell:

        1> cprof:start(), cprof:pause(). % Stop counters just after start
         8492
        -2> cprof:analyse().
        -{539,
        - [{shell,155,
        -         [{{shell,prep_check,1},55},
        -          {{shell,used_records,4},45},
        -          {{shell,used_records,1},45},
        -          {{shell,used_record_defs,2},1},
        -          {{shell,record_defs,2},1},
        -          {{shell,record_bindings,2},1},
        -          {{shell,exprs,7},1},
        -          {{shell,expr,4},1},
        -          {{shell,expand_records,2},1},
        -          {{shell,check_command,2},1},
        -          {{shell,apply_fun,3},1},
        -          {{shell,'-exprs/7-lc$^0/1-0-',1},1},
        -          {{shell,'-eval_loop/3-fun-0-',3},1}]},
        +2> cprof:analyse().
        +{539,
        + [{shell,155,
        +         [{{shell,prep_check,1},55},
        +          {{shell,used_records,4},45},
        +          {{shell,used_records,1},45},
        +          {{shell,used_record_defs,2},1},
        +          {{shell,record_defs,2},1},
        +          {{shell,record_bindings,2},1},
        +          {{shell,exprs,7},1},
        +          {{shell,expr,4},1},
        +          {{shell,expand_records,2},1},
        +          {{shell,check_command,2},1},
        +          {{shell,apply_fun,3},1},
        +          {{shell,'-exprs/7-lc$^0/1-0-',1},1},
        +          {{shell,'-eval_loop/3-fun-0-',3},1}]},
           %% Information about many modules omitted.
                              .
                              .
                              .
           %% Here is the last part.
        -  {erts_internal,2,[{{erts_internal,trace_pattern,3},2}]},
        -  {otp_internal,1,[{{otp_internal,obsolete,3},1}]},
        -  {maps,1,[{{maps,from_list,1},1}]},
        -  {erl_internal,1,[{{erl_internal,bif,3},1}]}]}
        -3> cprof:analyse(cprof).
        -{cprof,3,[{{cprof,tr,2},2},{{cprof,pause,0},1}]}
        -4> cprof:stop().
        +  {erts_internal,2,[{{erts_internal,trace_pattern,3},2}]},
        +  {otp_internal,1,[{{otp_internal,obsolete,3},1}]},
        +  {maps,1,[{{maps,from_list,1},1}]},
        +  {erl_internal,1,[{{erl_internal,bif,3},1}]}]}
        +3> cprof:analyse(cprof).
        +{cprof,3,[{{cprof,tr,2},2},{{cprof,pause,0},1}]}
        +4> cprof:stop().
         8586

        The example showed some of the background work that the shell performs just to interpret the first command line.

        What is captured in this example is the part of the work the shell does while interpreting the command line that occurs between the actual calls to -cprof:start() and cprof:analyse().

        Example: One module

        From the Erlang shell:

        1> cprof:start(),R=calendar:day_of_the_week(1896,4,27),cprof:pause(),R.
        +cprof:start() and cprof:analyse().

        Example: One module

        From the Erlang shell:

        1> cprof:start(),R=calendar:day_of_the_week(1896,4,27),cprof:pause(),R.
         1
        -2> cprof:analyse(calendar).
        -{calendar,9,
        -          [{{calendar,last_day_of_the_month1,2},1},
        -           {{calendar,last_day_of_the_month,2},1},
        -           {{calendar,is_leap_year1,1},1},
        -           {{calendar,is_leap_year,1},1},
        -           {{calendar,dy,1},1},
        -           {{calendar,dm,1},1},
        -           {{calendar,df,2},1},
        -           {{calendar,day_of_the_week,3},1},
        -           {{calendar,date_to_gregorian_days,3},1}]}
        -3> cprof:stop().
        +2> cprof:analyse(calendar).
        +{calendar,9,
        +          [{{calendar,last_day_of_the_month1,2},1},
        +           {{calendar,last_day_of_the_month,2},1},
        +           {{calendar,is_leap_year1,1},1},
        +           {{calendar,is_leap_year,1},1},
        +           {{calendar,dy,1},1},
        +           {{calendar,dm,1},1},
        +           {{calendar,df,2},1},
        +           {{calendar,day_of_the_week,3},1},
        +           {{calendar,date_to_gregorian_days,3},1}]}
        +3> cprof:stop().
         8648

        The example tells us that "Aktiebolaget LM Ericsson & Co" was registered on a Monday (since the return value of the first command is 1), and that the calendar module needed 9 function calls to calculate that.

        Using cprof:analyse() in this example also shows approximately the same -background work as in the first example.

        Example: In the code

        Write a module:

        -module(sort).
        --export([do/1]).
        +background work as in the first example.

        Example: In the code

        Write a module:

        -module(sort).
        +-export([do/1]).
         
        -do(N) ->
        -    cprof:stop(),
        -    cprof:start(),
        -    do(N, []).
        +do(N) ->
        +    cprof:stop(),
        +    cprof:start(),
        +    do(N, []).
         
        -do(0, L) ->
        -    R = lists:sort(L),
        -    cprof:pause(),
        +do(0, L) ->
        +    R = lists:sort(L),
        +    cprof:pause(),
             R;
        -do(N, L) ->
        -    do(N-1, [rand:uniform(256)-1 | L]).

        From the Erlang shell:

        1> c(sort).
        -{ok,sort}
        -2> rand:seed(default, 42), ok.
        +do(N, L) ->
        +    do(N-1, [rand:uniform(256)-1 | L]).

        From the Erlang shell:

        1> c(sort).
        +{ok,sort}
        +2> rand:seed(default, 42), ok.
         ok.
        -3> sort:do(1000).
        -[0,0,0,1,1,1,1,2,2,3,3,4,4,4,4,5,5,5,6,6,6,6,7,7,7,7,7,8,8|...]
        -4> cprof:analyse().
        -{13180,
        - [{lists,6173,
        -         [{{lists,rmerge3_1,6},1045},
        -          {{lists,rmerge3_2,6},977},
        -          {{lists,split_1,5},652},
        -          {{lists,merge3_1,6},579},
        -          {{lists,merge3_2,6},577},
        -          {{lists,rmerge3_12_3,6},511},
        -          {{lists,split_1_1,6},347},
        -          {{lists,merge3_12_3,6},310},
        -          {{lists,rmerge3_21_3,6},282},
        -          {{lists,merge3_21_3,6},221},
        -          {{lists,merge2_1,4},154},
        -          {{lists,merge2_2,5},138},
        -          {{lists,reverse,2},106},
        -          {{lists,rmerge2_2,5},87},
        -          {{lists,rmergel,2},81},
        -          {{lists,rmerge2_1,4},75},
        -          {{lists,mergel,2},28},
        -          {{lists,keyfind,3},2},
        -          {{lists,sort,1},1}]},
        -  {rand,5000,
        -        [{{rand,uniform_s,2},1000},
        -         {{rand,uniform,1},1000},
        -         {{rand,seed_put,1},1000},
        -         {{rand,seed_get,0},1000},
        -         {{rand,exsss_uniform,2},1000}]},
        -  {erlang,1004,
        -          [{{erlang,put,2},1000},
        -           {{erlang,trace_pattern,3},2},
        -           {{erlang,ensure_tracer_module_loaded,2},2}]},
        -  {sort,1001,[{{sort,do,2},1001}]},
        -  {erts_internal,2,[{{erts_internal,trace_pattern,3},2}]}]}
        -5> cprof:stop().
        +3> sort:do(1000).
        +[0,0,0,1,1,1,1,2,2,3,3,4,4,4,4,5,5,5,6,6,6,6,7,7,7,7,7,8,8|...]
        +4> cprof:analyse().
        +{13180,
        + [{lists,6173,
        +         [{{lists,rmerge3_1,6},1045},
        +          {{lists,rmerge3_2,6},977},
        +          {{lists,split_1,5},652},
        +          {{lists,merge3_1,6},579},
        +          {{lists,merge3_2,6},577},
        +          {{lists,rmerge3_12_3,6},511},
        +          {{lists,split_1_1,6},347},
        +          {{lists,merge3_12_3,6},310},
        +          {{lists,rmerge3_21_3,6},282},
        +          {{lists,merge3_21_3,6},221},
        +          {{lists,merge2_1,4},154},
        +          {{lists,merge2_2,5},138},
        +          {{lists,reverse,2},106},
        +          {{lists,rmerge2_2,5},87},
        +          {{lists,rmergel,2},81},
        +          {{lists,rmerge2_1,4},75},
        +          {{lists,mergel,2},28},
        +          {{lists,keyfind,3},2},
        +          {{lists,sort,1},1}]},
        +  {rand,5000,
        +        [{{rand,uniform_s,2},1000},
        +         {{rand,uniform,1},1000},
        +         {{rand,seed_put,1},1000},
        +         {{rand,seed_get,0},1000},
        +         {{rand,exsss_uniform,2},1000}]},
        +  {erlang,1004,
        +          [{{erlang,put,2},1000},
        +           {{erlang,trace_pattern,3},2},
        +           {{erlang,ensure_tracer_module_loaded,2},2}]},
        +  {sort,1001,[{{sort,do,2},1001}]},
        +  {erts_internal,2,[{{erts_internal,trace_pattern,3},2}]}]}
        +5> cprof:stop().
         12625

        The example shows some details of how lists:sort/1 works. It used 6173 function calls in module lists to complete the work.

        This time, since the shell was not involved in starting and stopping cprof, no other work was done in the system during the profiling.

        /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/cprof.xhtml differs (HTML document, ASCII text, with very long lines (1243)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/cprof.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/cprof.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -468,7 +468,7 @@ -

        Collects and analyses all call counters for module Module.

        This function returns:

        {Module, ModuleCount, FuncAnalysisList}

        where FuncAnalysisList is a list of tuples, one for each function:

        {{Module, FunctionName, Arity}, FuncCallCount}

        If call counters are still running while analyse/0,1,2 is executing, the result +

        Collects and analyses all call counters for module Module.

        This function returns:

        {Module, ModuleCount, FuncAnalysisList}

        where FuncAnalysisList is a list of tuples, one for each function:

        {{Module, FunctionName, Arity}, FuncCallCount}

        If call counters are still running while analyse/0,1,2 is executing, the result could be inconsistent. This happens if the process executing analyse/0,1,2 is scheduled out so some other process can increment the counters that are being analysed. Calling pause() before analysing takes care of /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/erlang-el.xhtml differs (HTML document, ASCII text, with very long lines (898)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/erlang-el.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/erlang-el.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -61,23 +61,23 @@ with almost the same argument as the preceding.

      Edit - Alignment

      • C-c C-a (align-current) - aligns comments, arrows, assignments, and type annotations around the cursor.
      Example:
       
      -sum(L) -> sum(L, 0).
      -sum([H|T], Sum) -> sum(T, Sum + H);  % recurse
      -sum([], Sum) -> Sum.   % base case
      +sum(L) -> sum(L, 0).
      +sum([H|T], Sum) -> sum(T, Sum + H);  % recurse
      +sum([], Sum) -> Sum.   % base case
       
      --record { two :: int(), % hello
      -          three = hello :: string(),    % there
      -          four = 42 :: int() }.
      +-record { two :: int(), % hello
      +          three = hello :: string(),    % there
      +          four = 42 :: int() }.
       
       becomes:
       
      -sum(L) -> sum(L, 0).
      -sum([H|T], Sum) -> sum(T, Sum + H); % recurse
      -sum([], Sum)    -> Sum.             % base case
      +sum(L) -> sum(L, 0).
      +sum([H|T], Sum) -> sum(T, Sum + H); % recurse
      +sum([], Sum)    -> Sum.             % base case
       
      --record { two           :: int(),    % hello
      -          three = hello :: string(), % there
      -          four  = 42    :: int() }.

      Syntax highlighting

      The syntax highlighting can be activated from the Erlang menu. There are four +-record { two :: int(), % hello + three = hello :: string(), % there + four = 42 :: int() }.

      Syntax highlighting

      The syntax highlighting can be activated from the Erlang menu. There are four different alternatives:

      • Off: Normal black and white display.
      • Level 1: Function headers, reserved words, comments, strings, quoted atoms, and character constants will be colored.
      • Level 2: The above, attributes, Erlang bif:s, guards, and words in comments enclosed in single quotes will be colored.
      • Level 3: The above, variables, records, and macros will be colored. (This /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/fprof_chapter.xhtml differs (HTML document, ASCII text, with very long lines (669)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/fprof_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/fprof_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -50,10 +50,10 @@ The tracing has to be stopped at a suitable later time using fprof:trace(stop).

        Immediate profiling

        It is also possible to trace immediately into the profiling process that creates the raw profile data, that is to short circuit the tracing and profiling steps -so that the filesystem is not used for tracing.

        Do something like this:

        {ok, Tracer} = fprof:profile(start),
        -fprof:trace([start, {tracer, Tracer}]),
        +so that the filesystem is not used for tracing.

        Do something like this:

        {ok, Tracer} = fprof:profile(start),
        +fprof:trace([start, {tracer, Tracer}]),
         %% Run code to profile
        -fprof:trace(stop);

        This puts less load on the filesystem, but much more load on the Erlang runtime +fprof:trace(stop);

        This puts less load on the filesystem, but much more load on the Erlang runtime system.

        /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/fprof.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1176)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/fprof.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/fprof.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -63,61 +63,61 @@ interested reader to try it out. Note that some flags to analyse/1 will affect the format.

        The following example was run on Erlang/OTP R8 on Solaris 8; all OTP internals in this example are version dependent.

        As an example, we will use the following function, which is a -slightly modified benchmark function from module file:

        -module(foo).
        --export([create_file_slow/2]).
        +slightly modified benchmark function from module file:

        -module(foo).
        +-export([create_file_slow/2]).
         
        -create_file_slow(Name, N) when is_integer(N), N >= 0 ->
        -    {ok, FD} =
        -        file:open(Name, [raw, write, delayed_write, binary]),
        +create_file_slow(Name, N) when is_integer(N), N >= 0 ->
        +    {ok, FD} =
        +        file:open(Name, [raw, write, delayed_write, binary]),
             if N > 256 ->
        -            ok = file:write(FD,
        -                            lists:map(fun (X) -> <<X:32/unsigned>> end,
        -                            lists:seq(0, 255))),
        -            ok = create_file_slow(FD, 256, N);
        +            ok = file:write(FD,
        +                            lists:map(fun (X) -> <<X:32/unsigned>> end,
        +                            lists:seq(0, 255))),
        +            ok = create_file_slow(FD, 256, N);
                true ->
        -            ok = create_file_slow(FD, 0, N)
        +            ok = create_file_slow(FD, 0, N)
             end,
        -    ok = file:close(FD).
        +    ok = file:close(FD).
         
        -create_file_slow(FD, M, M) ->
        +create_file_slow(FD, M, M) ->
             ok;
        -create_file_slow(FD, M, N) ->
        -    ok = file:write(FD, <<M:32/unsigned>>),
        -    create_file_slow(FD, M+1, N).

        Let us have a look at the printout after running:

        1> fprof:apply(foo, create_file_slow, [junk, 1024]).
        -2> fprof:profile().
        -3> fprof:analyse().

        The printout starts with:

        %% Analysis results:
        -{  analysis_options,
        - [{callers, true},
        -  {sort, acc},
        -  {totals, false},
        -  {details, true}]}.
        +create_file_slow(FD, M, N) ->
        +    ok = file:write(FD, <<M:32/unsigned>>),
        +    create_file_slow(FD, M+1, N).

        Let us have a look at the printout after running:

        1> fprof:apply(foo, create_file_slow, [junk, 1024]).
        +2> fprof:profile().
        +3> fprof:analyse().

        The printout starts with:

        %% Analysis results:
        +{  analysis_options,
        + [{callers, true},
        +  {sort, acc},
        +  {totals, false},
        +  {details, true}]}.
         
         %                                       CNT       ACC       OWN
        -[{ totals,                             9627, 1691.119, 1659.074}].  %%%

        The CNT column shows the total number of function calls that was found in the +[{ totals, 9627, 1691.119, 1659.074}]. %%%

        The CNT column shows the total number of function calls that was found in the trace. In the ACC column is the total time of the trace from first timestamp to last. And in the OWN column is the sum of the execution time in functions found in the trace, not including called functions. In this case it is very close to the ACC time since the emulator had practically nothing to do except executing our test program.

        All time values in the printout are in milliseconds.

        The printout continues:

        %                                       CNT       ACC       OWN
        -[{ "<0.28.0>",                         9627,undefined, 1659.074}].   %%

        This is the printout header of one process. The printout contains only this one +[{ "<0.28.0>", 9627,undefined, 1659.074}]. %%

    This is the printout header of one process. The printout contains only this one process since we called fprof:apply/3 that traces only the current process. Therefore the CNT and OWN columns perfectly matches the totals above. The ACC column is undefined since summing the ACC times of all calls in the process makes no sense — one would get something like the ACC value from totals above multiplied by the average depth of the call stack.

    All paragraphs up to the next process header only concerns function calls within -this process.

    Now we come to something more interesting:

    {[{undefined,                             0, 1691.076,    0.030}],
    - { {fprof,apply_start_stop,4},            0, 1691.076,    0.030},     %
    - [{{foo,create_file_slow,2},              1, 1691.046,    0.103},
    -  {suspend,                               1,    0.000,    0.000}]}.
    +this process.

    Now we come to something more interesting:

    {[{undefined,                             0, 1691.076,    0.030}],
    + { {fprof,apply_start_stop,4},            0, 1691.076,    0.030},     %
    + [{{foo,create_file_slow,2},              1, 1691.046,    0.103},
    +  {suspend,                               1,    0.000,    0.000}]}.
     
    -{[{{fprof,apply_start_stop,4},            1, 1691.046,    0.103}],
    - { {foo,create_file_slow,2},              1, 1691.046,    0.103},     %
    - [{{file,close,1},                        1, 1398.873,    0.019},
    -  {{foo,create_file_slow,3},              1,  249.678,    0.029},
    -  {{file,open,2},                         1,   20.778,    0.055},
    -  {{lists,map,2},                         1,   16.590,    0.043},
    -  {{lists,seq,2},                         1,    4.708,    0.017},
    -  {{file,write,2},                        1,    0.316,    0.021}]}.

    The printout consists of one paragraph per called function. The function +{[{{fprof,apply_start_stop,4}, 1, 1691.046, 0.103}], + { {foo,create_file_slow,2}, 1, 1691.046, 0.103}, % + [{{file,close,1}, 1, 1398.873, 0.019}, + {{foo,create_file_slow,3}, 1, 249.678, 0.029}, + {{file,open,2}, 1, 20.778, 0.055}, + {{lists,map,2}, 1, 16.590, 0.043}, + {{lists,seq,2}, 1, 4.708, 0.017}, + {{file,write,2}, 1, 0.316, 0.021}]}.

    The printout consists of one paragraph per called function. The function marked with % is the one the paragraph concerns — foo:create_file_slow/2. Above the marked function are the calling functions — those that has called the marked, and below are those called by the marked function.

    The paragraphs are per default sorted in descending order of the ACC column for @@ -134,12 +134,12 @@ (lists:seq/2 and lists:map/2).

    The function undefined that has called fprof:apply_start_stop/4 is an unknown function because that call was not recorded in the trace. It was only recorded that the execution returned from fprof:apply_start_stop/4 to some -other function above in the call stack, or that the process exited from there.

    Let us continue down the printout to find:

    {[{{foo,create_file_slow,2},              1,  249.678,    0.029},
    -  {{foo,create_file_slow,3},            768,    0.000,   23.294}],
    - { {foo,create_file_slow,3},            769,  249.678,   23.323},     %
    - [{{file,write,2},                      768,  220.314,   14.539},
    -  {suspend,                              57,    6.041,    0.000},
    -  {{foo,create_file_slow,3},            768,    0.000,   23.294}]}.

    If you compare with the code you will see there also that +other function above in the call stack, or that the process exited from there.

    Let us continue down the printout to find:

    {[{{foo,create_file_slow,2},              1,  249.678,    0.029},
    +  {{foo,create_file_slow,3},            768,    0.000,   23.294}],
    + { {foo,create_file_slow,3},            769,  249.678,   23.323},     %
    + [{{file,write,2},                      768,  220.314,   14.539},
    +  {suspend,                              57,    6.041,    0.000},
    +  {{foo,create_file_slow,3},            768,    0.000,   23.294}]}.

    If you compare with the code you will see there also that foo:create_file_slow/3 was called only from foo:create_file_slow/2 and itself, and called only file:write/2, note the number of calls to file:write/2. But here we see that suspend was called a few times. This is a @@ -147,88 +147,88 @@ foo:create_file_slow/3, and since there is no receive or erlang:yield/0 in the code, it must be Erlang scheduling suspensions, or the trace file driver compensating for large file write operations (these are regarded as a schedule -out followed by a schedule in to the same process).

    Let us find the suspend entry:

    {[{{file,write,2},                       53,    6.281,    0.000},
    -  {{foo,create_file_slow,3},             57,    6.041,    0.000},
    -  {{prim_file,drv_command,4},            50,    4.582,    0.000},
    -  {{prim_file,drv_get_response,1},       34,    2.986,    0.000},
    -  {{lists,map,2},                        10,    2.104,    0.000},
    -  {{prim_file,write,2},                  17,    1.852,    0.000},
    -  {{erlang,port_command,2},              15,    1.713,    0.000},
    -  {{prim_file,drv_command,2},            22,    1.482,    0.000},
    -  {{prim_file,translate_response,2},     11,    1.441,    0.000},
    -  {{prim_file,'-drv_command/2-fun-0-',1},  15,    1.340,    0.000},
    -  {{lists,seq,4},                         3,    0.880,    0.000},
    -  {{foo,'-create_file_slow/2-fun-0-',1},   5,    0.523,    0.000},
    -  {{erlang,bump_reductions,1},            4,    0.503,    0.000},
    -  {{prim_file,open_int_setopts,3},        1,    0.165,    0.000},
    -  {{prim_file,i32,4},                     1,    0.109,    0.000},
    -  {{fprof,apply_start_stop,4},            1,    0.000,    0.000}],
    - { suspend,                             299,   32.002,    0.000},     %
    - [ ]}.

    We find no particularly long suspend times, so no function seems to have waited +out followed by a schedule in to the same process).

    Let us find the suspend entry:

    {[{{file,write,2},                       53,    6.281,    0.000},
    +  {{foo,create_file_slow,3},             57,    6.041,    0.000},
    +  {{prim_file,drv_command,4},            50,    4.582,    0.000},
    +  {{prim_file,drv_get_response,1},       34,    2.986,    0.000},
    +  {{lists,map,2},                        10,    2.104,    0.000},
    +  {{prim_file,write,2},                  17,    1.852,    0.000},
    +  {{erlang,port_command,2},              15,    1.713,    0.000},
    +  {{prim_file,drv_command,2},            22,    1.482,    0.000},
    +  {{prim_file,translate_response,2},     11,    1.441,    0.000},
    +  {{prim_file,'-drv_command/2-fun-0-',1},  15,    1.340,    0.000},
    +  {{lists,seq,4},                         3,    0.880,    0.000},
    +  {{foo,'-create_file_slow/2-fun-0-',1},   5,    0.523,    0.000},
    +  {{erlang,bump_reductions,1},            4,    0.503,    0.000},
    +  {{prim_file,open_int_setopts,3},        1,    0.165,    0.000},
    +  {{prim_file,i32,4},                     1,    0.109,    0.000},
    +  {{fprof,apply_start_stop,4},            1,    0.000,    0.000}],
    + { suspend,                             299,   32.002,    0.000},     %
    + [ ]}.

    We find no particularly long suspend times, so no function seems to have waited in a receive statement. Actually, prim_file:drv_command/4 contains a receive statement, but in this test program, the message lies in the process receive buffer when the receive statement is entered. We also see that the total suspend time for the test run is small.

    The suspend pseudo function has an OWN time of zero. This is to prevent the process total OWN time from including time in suspension. Whether suspend -time is really ACC or OWN time is more of a philosophical question.

    Now we look at another interesting pseudo function, garbage_collect:

    {[{{prim_file,drv_command,4},            25,    0.873,    0.873},
    -  {{prim_file,write,2},                  16,    0.692,    0.692},
    -  {{lists,map,2},                         2,    0.195,    0.195}],
    - { garbage_collect,                      43,    1.760,    1.760},     %
    - [ ]}.

    Here we see that no function stands out, which is very normal.

    The garbage_collect pseudo function has not an OWN time of zero like +time is really ACC or OWN time is more of a philosophical question.

    Now we look at another interesting pseudo function, garbage_collect:

    {[{{prim_file,drv_command,4},            25,    0.873,    0.873},
    +  {{prim_file,write,2},                  16,    0.692,    0.692},
    +  {{lists,map,2},                         2,    0.195,    0.195}],
    + { garbage_collect,                      43,    1.760,    1.760},     %
    + [ ]}.

    Here we see that no function stands out, which is very normal.

    The garbage_collect pseudo function has not an OWN time of zero like suspend, instead it is equal to the ACC time.

    Garbage collection often occurs while a process is suspended, but fprof hides this fact by pretending that the suspended function was first unsuspended and then garbage collected. Otherwise the printout would show garbage_collect being called from suspend, but not which function that might have caused the -garbage collection.

    Let us now get back to the test code:

    {[{{foo,create_file_slow,3},            768,  220.314,   14.539},
    -  {{foo,create_file_slow,2},              1,    0.316,    0.021}],
    - { {file,write,2},                      769,  220.630,   14.560},     %
    - [{{prim_file,write,2},                 769,  199.789,   22.573},
    -  {suspend,                              53,    6.281,    0.000}]}.

    Not unexpectedly, we see that file:write/2 was called from +garbage collection.

    Let us now get back to the test code:

    {[{{foo,create_file_slow,3},            768,  220.314,   14.539},
    +  {{foo,create_file_slow,2},              1,    0.316,    0.021}],
    + { {file,write,2},                      769,  220.630,   14.560},     %
    + [{{prim_file,write,2},                 769,  199.789,   22.573},
    +  {suspend,                              53,    6.281,    0.000}]}.

    Not unexpectedly, we see that file:write/2 was called from foo:create_file_slow/3 and foo:create_file_slow/2. The number of calls in each case as well as the used time are also confirms the previous results.

    We see that file:write/2 only calls prim_file:write/2, but let us refrain from digging into the internals of the kernel application.

    If we nevertheless do dig down we find the call to the linked-in driver -that does the file operations towards the host operating system:

    {[{{prim_file,drv_command,4},           772, 1458.356, 1456.643}],
    - { {erlang,port_command,2},             772, 1458.356, 1456.643},     %
    - [{suspend,                              15,    1.713,    0.000}]}.

    This is 86 % of the total run time, and as we saw before it is the close +that does the file operations towards the host operating system:

    {[{{prim_file,drv_command,4},           772, 1458.356, 1456.643}],
    + { {erlang,port_command,2},             772, 1458.356, 1456.643},     %
    + [{suspend,                              15,    1.713,    0.000}]}.

    This is 86 % of the total run time, and as we saw before it is the close operation the absolutely biggest contributor. We find a comparison ratio a -little bit up in the call stack:

    {[{{prim_file,close,1},                   1, 1398.748,    0.024},
    -  {{prim_file,write,2},                 769,  174.672,   12.810},
    /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/lcnt_chapter.xhtml differs (HTML document, ASCII text, with very long lines (1944))
    --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/lcnt_chapter.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/lcnt_chapter.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -101,20 +101,20 @@
       <nonode@nohost.189.0>    5354          0.5230        118
       <nonode@nohost.121.0>    5845          0.9239        115
       <nonode@nohost.104.0>    5140          0.7782        108
    -ok

    Example with Mnesia Transaction Benchmark

    From the Erlang shell:

    Erlang/OTP 27 [erts-15.0] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [lock-counting]
    +ok

    Example with Mnesia Transaction Benchmark

    From the Erlang shell:

    Erlang/OTP 27 [erts-15.0] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [lock-counting]
     
    -Eshell V15.0 (press Ctrl+G to abort, type help(). for help)
    -1> Conf = [{db_nodes, [node()]}, {driver_nodes, [node()]}, {replica_nodes, [node()]},
    -    {n_drivers_per_node, 10}, {n_branches, 1000}, {n_accounts_per_branch, 10},
    -    {replica_type, ram_copies}, {stop_after, 60000}, {reuse_history_id, true}], ok.
    +Eshell V15.0 (press Ctrl+G to abort, type help(). for help)
    +1> Conf = [{db_nodes, [node()]}, {driver_nodes, [node()]}, {replica_nodes, [node()]},
    +    {n_drivers_per_node, 10}, {n_branches, 1000}, {n_accounts_per_branch, 10},
    +    {replica_type, ram_copies}, {stop_after, 60000}, {reuse_history_id, true}], ok.
     ok
    -2> mnesia_tpcb:init([{use_running_mnesia, false}|Conf]).
    +2> mnesia_tpcb:init([{use_running_mnesia, false}|Conf]).
         .
         .
         .
     ignore

    Initial configuring of the benchmark is done. It is time to profile the actual -Mnesia benchmark:

    3> lcnt:apply(fun() -> {ok,{time, Tps,_,_,_,_}} = mnesia_tpcb:run([{use_running_mnesia,
    -    true}|Conf]), Tps/60 end).
    +Mnesia benchmark:

    3> lcnt:apply(fun() -> {ok,{time, Tps,_,_,_,_}} = mnesia_tpcb:run([{use_running_mnesia,
    +    true}|Conf]), Tps/60 end).
           .
           .
           .
    @@ -206,63 +206,63 @@
     However, one should also look for high lock acquisition frequencies (#tries)
     since locks generate overhead and because high frequency could become
     problematic if they begin to have conflicts even if it is not shown in a
    -particular test.

    The Big Bang Benchmark

    -module(big).
    --export([bang/1]).
    +particular test.

    The Big Bang Benchmark

    -module(big).
    +-export([bang/1]).
     
    -pinger([], [], true) ->
    +pinger([], [], true) ->
         receive
    -	{procs, Procs, ReportTo} ->
    -	    pinger(Procs, [], ReportTo)
    +	{procs, Procs, ReportTo} ->
    +	    pinger(Procs, [], ReportTo)
         end;
    -pinger([], [], false) ->
    -    receive {ping, From} -> From ! {pong, self()} end,
    -    pinger([],[],false);
    -pinger([], [], ReportTo) ->
    -    ReportTo ! {done, self()},
    -    pinger([],[],false);
    -pinger([], [Po|Pos] = Pongers, ReportTo) ->
    +pinger([], [], false) ->
    +    receive {ping, From} -> From ! {pong, self()} end,
    +    pinger([],[],false);
    +pinger([], [], ReportTo) ->
    +    ReportTo ! {done, self()},
    +    pinger([],[],false);
    +pinger([], [Po|Pos] = Pongers, ReportTo) ->
         receive
    -	{ping, From} ->
    -	    From ! {pong, self()},
    -	    pinger([], Pongers, ReportTo);
    -	{pong, Po} ->
    -	    pinger([], Pos, ReportTo)
    +	{ping, From} ->
    +	    From ! {pong, self()},
    +	    pinger([], Pongers, ReportTo);
    +	{pong, Po} ->
    +	    pinger([], Pos, ReportTo)
         end;
    -pinger([Pi|Pis], Pongers, ReportTo) ->
    -    receive {ping, From} -> From ! {pong, self()}
    +pinger([Pi|Pis], Pongers, ReportTo) ->
    +    receive {ping, From} -> From ! {pong, self()}
         after 0 -> ok
         end,
    -    Pi ! {ping, self()},
    -    pinger(Pis, [Pi|Pongers], ReportTo).
    +    Pi ! {ping, self()},
    +    pinger(Pis, [Pi|Pongers], ReportTo).
     
    -spawn_procs(N) when N =< 0 ->
    -    [];
    -spawn_procs(N) ->
    -    [spawn_link(fun () -> pinger([],[],true) end) | spawn_procs(N-1)].
    +spawn_procs(N) when N =< 0 ->
    +    [];
    +spawn_procs(N) ->
    +    [spawn_link(fun () -> pinger([],[],true) end) | spawn_procs(N-1)].
     
    -send_procs([], Msg) ->
    +send_procs([], Msg) ->
         Msg;
    -send_procs([P|Ps], Msg) ->
    +send_procs([P|Ps], Msg) ->
         P ! Msg,
    -    send_procs(Ps, Msg).
    +    send_procs(Ps, Msg).
     
    -receive_msgs([]) ->
    +receive_msgs([]) ->
         ok;
    -receive_msgs([M|Ms]) ->
    +receive_msgs([M|Ms]) ->
         receive
     	M ->
    -	    receive_msgs(Ms)
    +	    receive_msgs(Ms)
         end.
     
    -bang(N) when integer(N) ->
    -    Procs = spawn_procs(N),
    -    RMsgs = lists:map(fun (P) -> {done, P} end, Procs),
    -    Start = now(),
    -    send_procs(Procs, {procs, Procs, self()}),
    -    receive_msgs(RMsgs),
    -    Stop = now(),
    -    lists:foreach(fun (P) -> exit(P, normal) end, Procs),
    -    timer:now_diff(Stop, Start).

    See Also

    LCNT Reference Manual

    +
    bang(N) when integer(N) -> + Procs = spawn_procs(N), + RMsgs = lists:map(fun (P) -> {done, P} end, Procs), + Start = now(), + send_procs(Procs, {procs, Procs, self()}), + receive_msgs(RMsgs), + Stop = now(), + lists:foreach(fun (P) -> exit(P, normal) end, Procs), + timer:now_diff(Stop, Start).

    See Also

    LCNT Reference Manual

    /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/make.xhtml differs (HTML document, ASCII text, with very long lines (793)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/make.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/make.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -30,8 +30,8 @@ the first match is used. For example, the following Emakefile means that file1 should be compiled with the options [debug_info,{i,"../foo"}], while all other files in the current directory should be compiled with only the -debug_info flag.

    {'file1',[debug_info,{i,"../foo"}]}.
    -{'*',[debug_info]}.

    See Also

    The Compiler Application

    +debug_info flag.

    {'file1',[debug_info,{i,"../foo"}]}.
    +{'*',[debug_info]}.

    See Also

    The Compiler Application

    /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/notes.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (8011)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -17,37 +17,37 @@

    Tools Release Notes

    -

    This document describes the changes made to the Tools application.

    Tools 4.1.4

    Improvements and New Features

    • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

      A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

      make release_docs places the documentation in the released code under the doc folder.

      make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

      The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

      Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

      Improves the source Software-Bill-of-Materials

      • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
      • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
      • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

      Own Id: OTP-19886 Aux Id: PR-10434

    Tools 4.1.3

    Improvements and New Features

    • Fixed some deprecations for newer emacs versions.

      Own Id: OTP-19726 Aux Id: PR-10106

    Tools 4.1.2

    Fixed Bugs and Malfunctions

    • A crash has been eliminated in tprof:collect/0 when unloading a module while collecting traces.

      Own Id: OTP-19135 Aux Id: GH-8483, PR-8547

    • Improved the indent-region Emacs command, which could indent badly when inside multiline string.

      Own Id: OTP-19396 Aux Id: PR-9186

    • eprof:start_profiling/3 can now return information about which process it failed to trace.

      Own Id: OTP-19419 Aux Id: PR-9219

    • Fixed a race condition when processes cause the Cover server to be started at the same time.

      Own Id: OTP-19517 Aux Id: PR-9124

    • Fix bug in tprof where the session name could not be set.

      Own Id: OTP-19580 Aux Id: PR-9648

    • Add tprof to the .app file.

      Own Id: OTP-19628 Aux Id: PR-9787

    Improvements and New Features

    • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

      Own Id: OTP-19575 Aux Id: PR-9670

    Tools 4.1.1

    Fixed Bugs and Malfunctions

    • Fixed some deprecated errors on emacs-29.

      Own Id: OTP-19273 Aux Id: PR-8879

    • The cover tool could sometimes wrongly report lines as uncovered.

      Own Id: OTP-19289 Aux Id: GH-8867, PR-8919

    • Fixed tprof:format(IoDevice, ...) to not demand unicode encoding supported by IoDevice.

      Own Id: OTP-19299 Aux Id: PR-8949

    Tools 4.1

    Fixed Bugs and Malfunctions

    • tprof no longer crashes when using pause/restart/continue when profiling all modules.

      Own Id: OTP-19136 Aux Id: GH-8472, PR-8472, PR-8541

    • On systems supporting native coverage, calls to cover could hang or crash if cover-compiled module had been reloaded from outside cover. This has been corrected so that cover now recovers from the error and and sends a report to the logger about the failure to retrieve coverage information.

      Own Id: OTP-19203 Aux Id: GH-8661, PR-8742

    Improvements and New Features

    • Figures in the documentation have been improved.

      Own Id: OTP-19130 Aux Id: PR-7226

    Tools 4.0

    Fixed Bugs and Malfunctions

    • Dialyzer warnings due to type specs added in dbg have been eliminated.

      Own Id: OTP-18860

    • In Erlang/OTP 26, doing a cover analysis on the line level would return multiple entries for lines on which multiple functions were defined.

      For example, consider this module:

      -module(foo).
      --export([bar/0, baz/0]).
      +

      This document describes the changes made to the Tools application.

      Tools 4.1.4

      Improvements and New Features

      • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

        A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

        make release_docs places the documentation in the released code under the doc folder.

        make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

        The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

        Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

        Improves the source Software-Bill-of-Materials

        • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
        • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
        • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

        Own Id: OTP-19886 Aux Id: PR-10434

      Tools 4.1.3

      Improvements and New Features

      • Fixed some deprecations for newer emacs versions.

        Own Id: OTP-19726 Aux Id: PR-10106

      Tools 4.1.2

      Fixed Bugs and Malfunctions

      • A crash has been eliminated in tprof:collect/0 when unloading a module while collecting traces.

        Own Id: OTP-19135 Aux Id: GH-8483, PR-8547

      • Improved the indent-region Emacs command, which could indent badly when inside multiline string.

        Own Id: OTP-19396 Aux Id: PR-9186

      • eprof:start_profiling/3 can now return information about which process it failed to trace.

        Own Id: OTP-19419 Aux Id: PR-9219

      • Fixed a race condition when processes cause the Cover server to be started at the same time.

        Own Id: OTP-19517 Aux Id: PR-9124

      • Fix bug in tprof where the session name could not be set.

        Own Id: OTP-19580 Aux Id: PR-9648

      • Add tprof to the .app file.

        Own Id: OTP-19628 Aux Id: PR-9787

      Improvements and New Features

      • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

        Own Id: OTP-19575 Aux Id: PR-9670

      Tools 4.1.1

      Fixed Bugs and Malfunctions

      • Fixed some deprecated errors on emacs-29.

        Own Id: OTP-19273 Aux Id: PR-8879

      • The cover tool could sometimes wrongly report lines as uncovered.

        Own Id: OTP-19289 Aux Id: GH-8867, PR-8919

      • Fixed tprof:format(IoDevice, ...) to not demand unicode encoding supported by IoDevice.

        Own Id: OTP-19299 Aux Id: PR-8949

      Tools 4.1

      Fixed Bugs and Malfunctions

      • tprof no longer crashes when using pause/restart/continue when profiling all modules.

        Own Id: OTP-19136 Aux Id: GH-8472, PR-8472, PR-8541

      • On systems supporting native coverage, calls to cover could hang or crash if cover-compiled module had been reloaded from outside cover. This has been corrected so that cover now recovers from the error and and sends a report to the logger about the failure to retrieve coverage information.

        Own Id: OTP-19203 Aux Id: GH-8661, PR-8742

      Improvements and New Features

      • Figures in the documentation have been improved.

        Own Id: OTP-19130 Aux Id: PR-7226

      Tools 4.0

      Fixed Bugs and Malfunctions

      • Dialyzer warnings due to type specs added in dbg have been eliminated.

        Own Id: OTP-18860

      • In Erlang/OTP 26, doing a cover analysis on the line level would return multiple entries for lines on which multiple functions were defined.

        For example, consider this module:

        -module(foo).
        +-export([bar/0, baz/0]).
         
        -bar() -> ok. baz() -> not_ok.

        In Erlang/OTP 26, analysing on the line level would return two entries -for line 4:

        1> cover:compile_module(foo).
        -{ok,foo}
        -2> foo:bar().
        +bar() -> ok. baz() -> not_ok.

        In Erlang/OTP 26, analysing on the line level would return two entries +for line 4:

        1> cover:compile_module(foo).
        +{ok,foo}
        +2> foo:bar().
         ok
        -3> cover:analyse(foo, coverage, line).
        -{ok,[{{foo,4},{1,0}},{{foo,4},{0,1}}]}
        -4> cover:analyse(foo, calls, line).
        -{ok,[{{foo,4},1},{{foo,4},0}]}

        In Erlang/OTP 27, there will only be a single entry for line 4:

        1> cover:compile_module(foo).
        -{ok,foo}
        -2> foo:bar().
        +3> cover:analyse(foo, coverage, line).
        +{ok,[{{foo,4},{1,0}},{{foo,4},{0,1}}]}
        +4> cover:analyse(foo, calls, line).
        +{ok,[{{foo,4},1},{{foo,4},0}]}

        In Erlang/OTP 27, there will only be a single entry for line 4:

        1> cover:compile_module(foo).
        +{ok,foo}
        +2> foo:bar().
         ok
        -3> cover:analyse(foo, coverage, line).
        -{ok,[{{foo,4},{1,0}}]}
        -4> cover:analyse(foo, calls, line).
        -{ok,[{{foo,4},1}]}

        Own Id: OTP-18998 Aux Id: GH-8159, PR-8182

      • Fixed align command in emacs mode.

        Own Id: OTP-19026 Aux Id: PR-8155

      Improvements and New Features

      • Triple-Quoted Strings has been implemented as per EEP 64. See String in the Reference Manual.

        Example:

        1> """
        +3> cover:analyse(foo, coverage, line).
        +{ok,[{{foo,4},{1,0}}]}
        +4> cover:analyse(foo, calls, line).
        +{ok,[{{foo,4},1}]}

        Own Id: OTP-18998 Aux Id: GH-8159, PR-8182

      • Fixed align command in emacs mode.

        Own Id: OTP-19026 Aux Id: PR-8155

      Improvements and New Features

      • Triple-Quoted Strings has been implemented as per EEP 64. See String in the Reference Manual.

        Example:

        1> """
            a
            b
            c
            """.
         "a\nb\nc"

        Adjacent string literals without intervening white space is now a syntax error, to avoid possible confusion with triple-quoted strings. For example:

        1> "abc""xyz".
         "xyz".
        -* 1:6: adjacent string literals without intervening white space

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-18750 Aux Id: OTP-18746, PR-7313, PR-7451

      • There is a new tool tprof, which combines the functionality of eprof and cprof under one interface and adds heap profiling. It also has functionality to help with profiling process hierarchies.

        Example:

        1> tprof:profile(lists, seq, [1, 16], #{type => call_memory}).
        +* 1:6: adjacent string literals without intervening white space

        POTENTIAL INCOMPATIBILITY

        Own Id: OTP-18750 Aux Id: OTP-18746, PR-7313, PR-7451

      • There is a new tool tprof, which combines the functionality of eprof and cprof under one interface and adds heap profiling. It also has functionality to help with profiling process hierarchies.

        Example:

        1> tprof:profile(lists, seq, [1, 16], #{type => call_memory}).
         
         ****** Process <0.92.0>  --  100.00% of total *** 
        -FUNCTION          CALLS  WORDS  PER CALL  [     %]
        -lists:seq_loop/3      5     32      6.40  [100.00]
        -                            32            [ 100.0]
        +FUNCTION          CALLS  WORDS  PER CALL  [     %]
        +lists:seq_loop/3      5     32      6.40  [100.00]
        +                            32            [ 100.0]
         ok

        Own Id: OTP-18756 Aux Id: PR-6639

      • Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code.

        There are also new APIs to support native coverage without using the cover tool.

        To instrument code for native coverage it must be compiled with the line_coverage option.

        To enable native coverage in the runtime system, start it like so:

        $ erl +JPcover true

        There are also the following new functions for supporting native coverage:

        Own Id: OTP-18856 Aux Id: PR-7856

      • The documentation has been migrated to use Markdown and ExDoc.

        Own Id: OTP-18955 Aux Id: PR-8026

      • Improved the align command in emacs mode.

        Own Id: OTP-19080 Aux Id: PR-8288

      Tools 3.6

      Improvements and New Features

      • Map comprehensions as suggested in EEP 58 has now been implemented.

        Own Id: OTP-18413 Aux Id: EEP-58, PR-6727

      • The instrument module has been moved from tools to runtime_tools.

        Own Id: OTP-18487 Aux Id: PR-6829

      Tools 3.5.3

      Improvements and New Features

      • Removed the previously undocumented and unsupported emem tool.

        Own Id: OTP-17892 Aux Id: PR-5591

      Tools 3.5.2

      Fixed Bugs and Malfunctions

      • Erlang-mode fixed for newer versions of xref using CL-Lib structures instead of EIEIO classes.

        Own Id: OTP-17746 Aux Id: GH-5314, PR-5324

      Tools 3.5.1

      Fixed Bugs and Malfunctions

      • The cover tool would not work on modules compiled with the tuple_calls option.

        Own Id: OTP-17440 Aux Id: GH-4796

      Tools 3.5

      Fixed Bugs and Malfunctions

      • For cover-compiled code, the error behaviour of list and binary comprehensions /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/tprof.xhtml differs (HTML document, ASCII text, with very long lines (1237)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/tprof.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/tprof.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -48,185 +48,185 @@ trace all functions.

        Warning

        Avoid hot code reloading for modules participating in the tracing. Reloading a module disables tracing and discards the accumulated statistics. The tprof results will probably be incorrect when the profiled code was -reloading during a profiling session.

        Ad-hoc profiling

        Ad-hoc profiling is convenient for profiling a single function call.

        For example:

        1> tprof:profile(lists, seq, [1, 16], #{type => call_memory}).
        +reloading during a profiling session.

        Ad-hoc profiling

        Ad-hoc profiling is convenient for profiling a single function call.

        For example:

        1> tprof:profile(lists, seq, [1, 16], #{type => call_memory}).
         
         ****** Process <0.92.0>  --  100.00% of total *** 
        -FUNCTION          CALLS  WORDS  PER CALL  [     %]
        -lists:seq_loop/3      5     32      6.40  [100.00]
        -                            32            [ 100.0]
        +FUNCTION          CALLS  WORDS  PER CALL  [     %]
        +lists:seq_loop/3      5     32      6.40  [100.00]
        +                            32            [ 100.0]
         ok

        By default tracing is enabled for all functions in all modules. When funs -are created in the interactive shell, parts of shell code are also traced:

        1> tprof:profile(fun() -> lists:seq(1, 16) end, #{type => call_memory}).
        +are created in the interactive shell, parts of shell code are also traced:

        1> tprof:profile(fun() -> lists:seq(1, 16) end, #{type => call_memory}).
         
         ****** Process <0.95.0>  --  100.00% of total *** 
        -FUNCTION                   CALLS  WORDS  PER CALL  [    %]
        -erl_eval:do_apply/7            1      3      3.00  [ 3.61]
        -erl_eval:match_list/6          1      3      3.00  [ 3.61]
        -lists:reverse/1                1      4      4.00  [ 4.82]
        -erl_eval:expr_list/7           3      7      2.33  [ 8.43]
        -erl_eval:ret_expr/3            4     16      4.00  [19.28]
        -erl_eval:merge_bindings/4      3     18      6.00  [21.69]
        -lists:seq_loop/3               5     32      6.40  [38.55]
        -                                     83            [100.0]
        -ok

        However, it is possible to limit the trace to specific functions or modules:

        2> tprof:profile(fun() -> lists:seq(1, 16) end,
        -                 #{type => call_memory, pattern => [{lists, seq_loop, '_'}]}).
        +FUNCTION                   CALLS  WORDS  PER CALL  [    %]
        +erl_eval:do_apply/7            1      3      3.00  [ 3.61]
        +erl_eval:match_list/6          1      3      3.00  [ 3.61]
        +lists:reverse/1                1      4      4.00  [ 4.82]
        +erl_eval:expr_list/7           3      7      2.33  [ 8.43]
        +erl_eval:ret_expr/3            4     16      4.00  [19.28]
        +erl_eval:merge_bindings/4      3     18      6.00  [21.69]
        +lists:seq_loop/3               5     32      6.40  [38.55]
        +                                     83            [100.0]
        +ok

        However, it is possible to limit the trace to specific functions or modules:

        2> tprof:profile(fun() -> lists:seq(1, 16) end,
        +                 #{type => call_memory, pattern => [{lists, seq_loop, '_'}]}).
         ****** Process <0.98.0>  --  100.00% of total *** 
        -FUNCTION          CALLS  WORDS  PER CALL  [     %]
        -lists:seq_loop/3      5     32      6.40  [100.00]
        -                            32            [ 100.0]
        +FUNCTION          CALLS  WORDS  PER CALL  [     %]
        +lists:seq_loop/3      5     32      6.40  [100.00]
        +                            32            [ 100.0]
         
         ok

        Ad-hoc profiling results can be printed in a few different ways. The following -examples use the test module defined like this:

        -module(test).
        --export([test_spawn/0]).
        -test_spawn() ->
        -    {Pid, MRef} = spawn_monitor(fun () -> lists:seq(1, 32) end),
        +examples use the test module defined like this:

        -module(test).
        +-export([test_spawn/0]).
        +test_spawn() ->
        +    {Pid, MRef} = spawn_monitor(fun () -> lists:seq(1, 32) end),
             receive
        -        {'DOWN', MRef, process, Pid, normal} ->
        +        {'DOWN', MRef, process, Pid, normal} ->
                     done
        -    end.

        By default per-process statistics is shown:

        1> tprof:profile(test, test_spawn, [], #{type => call_memory}).
        +    end.

        By default per-process statistics is shown:

        1> tprof:profile(test, test_spawn, [], #{type => call_memory}).
         
         ****** Process <0.176.0>    -- 23.66 % of total allocations ***
        -FUNCTION                CALLS  WORDS  PER CALL  [    %]
        -erlang:spawn_monitor/1      1      2         2  [ 9.09]
        -erlang:spawn_opt/4          1      6         6  [27.27]
        -test:test_spawn/0           1     14        14  [63.64]
        -                                  22            [100.0]
        +FUNCTION                CALLS  WORDS  PER CALL  [    %]
        +erlang:spawn_monitor/1      1      2         2  [ 9.09]
        +erlang:spawn_opt/4          1      6         6  [27.27]
        +test:test_spawn/0           1     14        14  [63.64]
        +                                  22            [100.0]
         
         ****** Process <0.177.0>    -- 76.34 % of total allocations ***
        -FUNCTION           CALLS  WORDS  PER CALL  [    %]
        -erlang:apply/2         1      7         7  [ 9.86]
        -lists:seq_loop/3       9     64         7  [90.14]
        -                             71            [100.0]

        The following example prints the combined memory allocation of all +FUNCTION CALLS WORDS PER CALL [ %] +erlang:apply/2 1 7 7 [ 9.86] +lists:seq_loop/3 9 64 7 [90.14] + 71 [100.0]

        The following example prints the combined memory allocation of all processes, sorted by the total number of allocated words in descending -order:

        2> tprof:profile(test, test_spawn, [],
        -                 #{type => call_memory, report => {total, {measurement, descending}}}).
        +order:

        2> tprof:profile(test, test_spawn, [],
        +                 #{type => call_memory, report => {total, {measurement, descending}}}).
         
        -FUNCTION                CALLS  WORDS  PER CALL  [    %]
        -lists:seq_loop/3            9     64         7  [68.82]
        -test:test_spawn/0           1     14        14  [15.05]
        -erlang:apply/2              1      7         7  [ 7.53]
        -erlang:spawn_opt/4          1      6         6  [ 6.45]
        -erlang:spawn_monitor/1      1      2         2  [ 2.15]
        -                                  93            [100.0]

        The profiling data can also be collected for further inspection:

        3> {done, ProfileData} = tprof:profile(fun test:test_spawn/0,
        -                                       #{type => call_memory, report => return}).
        +FUNCTION                CALLS  WORDS  PER CALL  [    %]
        +lists:seq_loop/3            9     64         7  [68.82]
        +test:test_spawn/0           1     14        14  [15.05]
        +erlang:apply/2              1      7         7  [ 7.53]
        +erlang:spawn_opt/4          1      6         6  [ 6.45]
        +erlang:spawn_monitor/1      1      2         2  [ 2.15]
        +                                  93            [100.0]

        The profiling data can also be collected for further inspection:

        3> {done, ProfileData} = tprof:profile(fun test:test_spawn/0,
        +                                       #{type => call_memory, report => return}).
         <...>
        -4> tprof:format(tprof:inspect(ProfileData, process, {percent, descending})).
        +4> tprof:format(tprof:inspect(ProfileData, process, {percent, descending})).
         
         ****** Process <0.223.0>    -- 23.66 % of total allocations ***
        -FUNCTION                CALLS  WORDS  PER CALL  [    %]
        -test:test_spawn/0           1     14        14  [63.64]
        -erlang:spawn_opt/4          1      6         6  [27.27]
        -erlang:spawn_monitor/1      1      2         2  [ 9.09]
        -                                  22            [100.0]
        +FUNCTION                CALLS  WORDS  PER CALL  [    %]
        +test:test_spawn/0           1     14        14  [63.64]
        +erlang:spawn_opt/4          1      6         6  [27.27]
        +erlang:spawn_monitor/1      1      2         2  [ 9.09]
        +                                  22            [100.0]
         
         ****** Process <0.224.0>    -- 76.34 % of total allocations ***
        -FUNCTION           CALLS  WORDS  PER CALL  [    %]
        -lists:seq_loop/3       9     64         7  [90.14]
        -erlang:apply/2         1      7         7  [ 9.86]
        -                             71            [100.0]

        Which processes that are profiled depends on the profiling type.

        • call_count (default) counts calls in all processes.

        • call_time and call_memory limits the profiling to the processes +FUNCTION CALLS WORDS PER CALL [ %] +lists:seq_loop/3 9 64 7 [90.14] +erlang:apply/2 1 7 7 [ 9.86] + 71 [100.0]

        Which processes that are profiled depends on the profiling type.

        • call_count (default) counts calls in all processes.

        • call_time and call_memory limits the profiling to the processes spawned from the user-provided function (using the set_on_spawn -option for trace:process/4).

        call_time and call_memory can be restricted to profile a single process:

        2> tprof:profile(test, test_spawn, [],
        -                 #{type => call_memory, set_on_spawn => false}).
        +option for trace:process/4).

      call_time and call_memory can be restricted to profile a single process:

      2> tprof:profile(test, test_spawn, [],
      +                 #{type => call_memory, set_on_spawn => false}).
       
       ****** Process <0.183.0>    -- 100.00 % of total allocations ***
      -FUNCTION                CALLS  WORDS  PER CALL  [    %]
      -erlang:spawn_monitor/1      1      2         2  [ 9.09]
      -erlang:spawn_opt/4          1      6         6  [27.27]
      -test:test_spawn/0           1     14        14  [63.64]

      Erlang programs can perform expensive operations in other processes +FUNCTION CALLS WORDS PER CALL [ %] +erlang:spawn_monitor/1 1 2 2 [ 9.09] +erlang:spawn_opt/4 1 6 6 [27.27] +test:test_spawn/0 1 14 14 [63.64]

      Erlang programs can perform expensive operations in other processes than the original one. You can include multiple, new, or even all -processes in the trace when measuring time or memory:

      7> pg:start_link().
      -{ok,<0.252.0>}
      -8> tprof:profile(fun() -> pg:join(group, self()) end,
      -                 #{type => call_memory, rootset => [pg]}).
      +processes in the trace when measuring time or memory:

      7> pg:start_link().
      +{ok,<0.252.0>}
      +8> tprof:profile(fun() -> pg:join(group, self()) end,
      +                 #{type => call_memory, rootset => [pg]}).
       ****** Process <0.252.0>    -- 52.86 % of total allocations ***
      -FUNCTION                      CALLS  WORDS  PER CALL  [    %]
      -pg:leave_local_update_ets/5       1      2         2  [ 1.80]
      -gen:reply/2                       1      3         3  [ 2.70]
      -erlang:monitor/2                  1      3         3  [ 2.70]
      -gen_server:try_handle_call/4      1      3         3  [ 2.70]
      -gen_server:try_dispatch/4         1      3         3  [ 2.70]
      -maps:iterator/1                   2      4         2  [ 3.60]
      -maps:take/2                       1      6         6  [ 5.41]
      -pg:join_local_update_ets/5        1      8         8  [ 7.21]
      -pg:handle_info/2                  1      8         8  [ 7.21]
      -pg:handle_call/3                  1      9         9  [ 8.11]
      -gen_server:loop/7                 2      9         4  [ 8.11]
      -ets:lookup/2                      2     10         5  [ 9.01]
      -pg:join_local/3                   1     11        11  [ 9.91]
      -pg:notify_group/5                 2     16         8  [14.41]
      -erlang:setelement/3               2     16         8  [14.41]
      -                                       111            [100.0]
      +FUNCTION                      CALLS  WORDS  PER CALL  [    %]
      +pg:leave_local_update_ets/5       1      2         2  [ 1.80]
      +gen:reply/2                       1      3         3  [ 2.70]
      +erlang:monitor/2                  1      3         3  [ 2.70]
      +gen_server:try_handle_call/4      1      3         3  [ 2.70]
      +gen_server:try_dispatch/4         1      3         3  [ 2.70]
      +maps:iterator/1                   2      4         2  [ 3.60]
      +maps:take/2                       1      6         6  [ 5.41]
      +pg:join_local_update_ets/5        1      8         8  [ 7.21]
      +pg:handle_info/2                  1      8         8  [ 7.21]
      +pg:handle_call/3                  1      9         9  [ 8.11]
      +gen_server:loop/7                 2      9         4  [ 8.11]
      +ets:lookup/2                      2     10         5  [ 9.01]
      +pg:join_local/3                   1     11        11  [ 9.91]
      +pg:notify_group/5                 2     16         8  [14.41]
      +erlang:setelement/3               2     16         8  [14.41]
      +                                       111            [100.0]
       
       ****** Process <0.255.0>    -- 47.14 % of total allocations ***
      -FUNCTION                   CALLS  WORDS  PER CALL  [    %]
      -erl_eval:match_list/6          1      3         3  [ 3.03]
      -erlang:monitor/2               1      3         3  [ 3.03]
      -lists:reverse/1                2      4         2  [ 4.04]
      /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/xref_chapter.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (993))
      --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/xref_chapter.xhtml	2026-08-05 05:56:49.000000000 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tools.epub/OEBPS/xref_chapter.xhtml	2026-08-05 05:56:49.000000000 +0000
      @@ -26,25 +26,25 @@
       system and for doing some simple graph analyses on selected calls.

      The following sections show some features of Xref, beginning with a module check and a predefined analysis. Then follow examples that can be skipped on the first reading; not all of the concepts used are explained, and it is assumed that the -reference manual has been at least skimmed.

      Module Check

      Assume we want to check the following module:

      -module(my_module).
      +reference manual has been at least skimmed.

      Module Check

      Assume we want to check the following module:

      -module(my_module).
       
      --export([t/1]).
      +-export([t/1]).
       
      -t(A) ->
      -  my_module:t2(A).
      +t(A) ->
      +  my_module:t2(A).
       
      -t2(_) ->
      +t2(_) ->
         true.

      Cross reference data are read from BEAM files, so the first step when checking -an edited module is to compile it:

      1> c(my_module, debug_info).
      +an edited module is to compile it:

      1> c(my_module, debug_info).
       ./my_module.erl:10: Warning: function t2/1 is unused
      -{ok, my_module}

      The debug_info option ensures that the BEAM file contains debug information, +{ok, my_module}

      The debug_info option ensures that the BEAM file contains debug information, which makes it possible to find unused local functions.

      The module can now be checked for calls to deprecated functions, calls to undefined functions, and for unused local -functions:

      2> xref:m(my_module)
      -[{deprecated,[]},
      - {undefined,[{{my_module,t,1},{my_module,t2,1}}]},
      - {unused,[{my_module,t2,1}]}]

      m/1 is also suitable for checking that the BEAM file of a module that is about +functions:

      2> xref:m(my_module)
      +[{deprecated,[]},
      + {undefined,[{{my_module,t,1},{my_module,t2,1}}]},
      + {unused,[{my_module,t2,1}]}]

      m/1 is also suitable for checking that the BEAM file of a module that is about to be loaded into a running a system does not call any undefined functions. In either case, the code path of the code server (see the module code) is used for finding modules that export externally called functions not exported by the @@ -53,28 +53,28 @@ this example an xref server will be used, which makes it possible to analyze applications and releases, and also to select the library path explicitly.

      Each Xref server is referred to by a unique name. The name is given when -creating the server:

      1> xref:start(s).
      -{ok,<0.27.0>}

      Next the system to be analyzed is added to the Xref server. Here the system will +creating the server:

      1> xref:start(s).
      +{ok,<0.27.0>}

      Next the system to be analyzed is added to the Xref server. Here the system will be OTP, so no library path will be needed. Otherwise, when analyzing a system that uses OTP, the OTP modules are typically made library modules by setting the library path to the default OTP code path (or to code_path, see the reference manual). By default, the names of read BEAM files and warnings are output when adding analyzed modules, but these messages -can be avoided by setting default values of some options:

      2> xref:set_default(s, [{verbose,false}, {warnings,false}]).
      +can be avoided by setting default values of some options:

      2> xref:set_default(s, [{verbose,false}, {warnings,false}]).
       ok
      -3> xref:add_release(s, code:lib_dir(), {name, otp}).
      -{ok,otp}

      add_release/3 assumes that all subdirectories of the library directory +3> xref:add_release(s, code:lib_dir(), {name, otp}). +{ok,otp}

      add_release/3 assumes that all subdirectories of the library directory returned by code:lib_dir() contain applications; -the effect is that of reading all BEAM files for the application.

      It is now easy to check the release for calls to undefined functions:

      4> xref:analyze(s, undefined_function_calls).
      -{ok, [...]}

      We can now continue with further analyses, or we can delete the Xref server:

      5> xref:stop(s).

      The check for calls to undefined functions is an example of a predefined +the effect is that of reading all BEAM files for the application.

      It is now easy to check the release for calls to undefined functions:

      4> xref:analyze(s, undefined_function_calls).
      +{ok, [...]}

      We can now continue with further analyses, or we can delete the Xref server:

      5> xref:stop(s).

      The check for calls to undefined functions is an example of a predefined analysis, probably the most useful one. Other examples are the analyses that find unused local functions, or functions that call some given functions. See the analyze/2,3 functions for a complete list of predefined analyses.

      Each predefined analysis is a shorthand for a query, a sentence of a tiny language providing cross reference data as values of predefined variables. The check for calls to -undefined functions can thus be stated as a query:

      4> xref:q(s, "(XC - UC) || (XU - X - B)").
      -{ok,[...]}

      The query asks for the restriction of external calls except the unresolved calls +undefined functions can thus be stated as a query:

      4> xref:q(s, "(XC - UC) || (XU - X - B)").
      +{ok,[...]}

      The query asks for the restriction of external calls except the unresolved calls to calls to functions that are externally used but neither exported nor built-in functions (the || operator restricts the used functions while the | operator restricts the calling functions). The - operator returns the difference of two @@ -98,8 +98,8 @@ provided with a simple language. Below are some expressions of the language with comments, focusing on elements of the language rather than providing useful examples. The analyzed system is assumed to be OTP, so in order to run the -queries, first evaluate these calls:

      xref:start(s).
      -xref:add_release(s, code:root_dir()).
      • xref:q(s, "(Fun) xref : Mod"). - All functions of the xref module.

      • xref:q(s, "xref : Mod * X"). - All exported functions of the xref +queries, first evaluate these calls:

        xref:start(s).
        +xref:add_release(s, code:root_dir()).
        • xref:q(s, "(Fun) xref : Mod"). - All functions of the xref module.

        • xref:q(s, "xref : Mod * X"). - All exported functions of the xref module. The first operand of the intersection operator * is implicitly converted to the more special type of the second operand.

        • xref:q(s, "(Mod) tools"). - All modules of the Tools application.

        • xref:q(s, '"xref_.*" : Mod'). - All modules with a name beginning with xref_.

        • xref:q(s, "# E | X "). - Number of calls from exported functions.

        • xref:q(s, "XC || L "). - All external calls to local functions.

        • xref:q(s, "XC * LC"). - All calls that have both an external and a local @@ -136,18 +136,18 @@ a module M1 is said to call a module M2 if there is some function in M1 that calls some function in M2. It would be nice if we could use the much smaller module graph, since it is available also in the light weight -modulesmode of Xref servers.

          t(S) ->
          -  {ok, _} = xref:q(S, "Eplus := closure E"),
          -  {ok, Ms} = xref:q(S, "AM"),
          -  Fun = fun(M, N) ->
          -      Q = io_lib:format("# (Mod) (Eplus | ~p : Mod)", [M]),
          -      {ok, N0} = xref:q(S, lists:flatten(Q)),
          +modulesmode of Xref servers.

          t(S) ->
          +  {ok, _} = xref:q(S, "Eplus := closure E"),
          +  {ok, Ms} = xref:q(S, "AM"),
          +  Fun = fun(M, N) ->
          +      Q = io_lib:format("# (Mod) (Eplus | ~p : Mod)", [M]),
          +      {ok, N0} = xref:q(S, lists:flatten(Q)),
                 N + N0
               end,
          -  Sum = lists:foldl(Fun, 0, Ms),
          -  ok = xref:forget(S, 'Eplus'),
          -  {ok, Tot} = xref:q(S, "# (closure ME | AM)"),
          -  100 * ((Tot - Sum) / Tot).

          Comments on the code:

          • We want to find the reduction of the closure of the function graph to modules. + Sum = lists:foldl(Fun, 0, Ms), + ok = xref:forget(S, 'Eplus'), + {ok, Tot} = xref:q(S, "# (closure ME | AM)"), + 100 * ((Tot - Sum) / Tot).

          Comments on the code:

          • We want to find the reduction of the closure of the function graph to modules. The direct expression for doing that would be (Mod) (closure E | AM), but then we would have to represent all of the transitive closure of E in memory. Instead the number of indirectly used modules is found for each analyzed /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tprof.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1311)) --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tprof.html 2026-08-21 04:00:32.176377778 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/tprof.html 2026-08-21 04:00:32.176377778 +0000 @@ -119,185 +119,185 @@ trace all functions.

            Warning

            Avoid hot code reloading for modules participating in the tracing. Reloading a module disables tracing and discards the accumulated statistics. The tprof results will probably be incorrect when the profiled code was -reloading during a profiling session.

            Ad-hoc profiling

            Ad-hoc profiling is convenient for profiling a single function call.

            For example:

            1> tprof:profile(lists, seq, [1, 16], #{type => call_memory}).
            +reloading during a profiling session.

            Ad-hoc profiling

            Ad-hoc profiling is convenient for profiling a single function call.

            For example:

            1> tprof:profile(lists, seq, [1, 16], #{type => call_memory}).
             
             ****** Process <0.92.0>  --  100.00% of total *** 
            -FUNCTION          CALLS  WORDS  PER CALL  [     %]
            -lists:seq_loop/3      5     32      6.40  [100.00]
            -                            32            [ 100.0]
            +FUNCTION          CALLS  WORDS  PER CALL  [     %]
            +lists:seq_loop/3      5     32      6.40  [100.00]
            +                            32            [ 100.0]
             ok

            By default tracing is enabled for all functions in all modules. When funs -are created in the interactive shell, parts of shell code are also traced:

            1> tprof:profile(fun() -> lists:seq(1, 16) end, #{type => call_memory}).
            +are created in the interactive shell, parts of shell code are also traced:

            1> tprof:profile(fun() -> lists:seq(1, 16) end, #{type => call_memory}).
             
             ****** Process <0.95.0>  --  100.00% of total *** 
            -FUNCTION                   CALLS  WORDS  PER CALL  [    %]
            -erl_eval:do_apply/7            1      3      3.00  [ 3.61]
            -erl_eval:match_list/6          1      3      3.00  [ 3.61]
            -lists:reverse/1                1      4      4.00  [ 4.82]
            -erl_eval:expr_list/7           3      7      2.33  [ 8.43]
            -erl_eval:ret_expr/3            4     16      4.00  [19.28]
            -erl_eval:merge_bindings/4      3     18      6.00  [21.69]
            -lists:seq_loop/3               5     32      6.40  [38.55]
            -                                     83            [100.0]
            -ok

            However, it is possible to limit the trace to specific functions or modules:

            2> tprof:profile(fun() -> lists:seq(1, 16) end,
            -                 #{type => call_memory, pattern => [{lists, seq_loop, '_'}]}).
            +FUNCTION                   CALLS  WORDS  PER CALL  [    %]
            +erl_eval:do_apply/7            1      3      3.00  [ 3.61]
            +erl_eval:match_list/6          1      3      3.00  [ 3.61]
            +lists:reverse/1                1      4      4.00  [ 4.82]
            +erl_eval:expr_list/7           3      7      2.33  [ 8.43]
            +erl_eval:ret_expr/3            4     16      4.00  [19.28]
            +erl_eval:merge_bindings/4      3     18      6.00  [21.69]
            +lists:seq_loop/3               5     32      6.40  [38.55]
            +                                     83            [100.0]
            +ok

            However, it is possible to limit the trace to specific functions or modules:

            2> tprof:profile(fun() -> lists:seq(1, 16) end,
            +                 #{type => call_memory, pattern => [{lists, seq_loop, '_'}]}).
             ****** Process <0.98.0>  --  100.00% of total *** 
            -FUNCTION          CALLS  WORDS  PER CALL  [     %]
            -lists:seq_loop/3      5     32      6.40  [100.00]
            -                            32            [ 100.0]
            +FUNCTION          CALLS  WORDS  PER CALL  [     %]
            +lists:seq_loop/3      5     32      6.40  [100.00]
            +                            32            [ 100.0]
             
             ok

            Ad-hoc profiling results can be printed in a few different ways. The following -examples use the test module defined like this:

            -module(test).
            --export([test_spawn/0]).
            -test_spawn() ->
            -    {Pid, MRef} = spawn_monitor(fun () -> lists:seq(1, 32) end),
            +examples use the test module defined like this:

            -module(test).
            +-export([test_spawn/0]).
            +test_spawn() ->
            +    {Pid, MRef} = spawn_monitor(fun () -> lists:seq(1, 32) end),
                 receive
            -        {'DOWN', MRef, process, Pid, normal} ->
            +        {'DOWN', MRef, process, Pid, normal} ->
                         done
            -    end.

            By default per-process statistics is shown:

            1> tprof:profile(test, test_spawn, [], #{type => call_memory}).
            +    end.

            By default per-process statistics is shown:

            1> tprof:profile(test, test_spawn, [], #{type => call_memory}).
             
             ****** Process <0.176.0>    -- 23.66 % of total allocations ***
            -FUNCTION                CALLS  WORDS  PER CALL  [    %]
            -erlang:spawn_monitor/1      1      2         2  [ 9.09]
            -erlang:spawn_opt/4          1      6         6  [27.27]
            -test:test_spawn/0           1     14        14  [63.64]
            -                                  22            [100.0]
            +FUNCTION                CALLS  WORDS  PER CALL  [    %]
            +erlang:spawn_monitor/1      1      2         2  [ 9.09]
            +erlang:spawn_opt/4          1      6         6  [27.27]
            +test:test_spawn/0           1     14        14  [63.64]
            +                                  22            [100.0]
             
             ****** Process <0.177.0>    -- 76.34 % of total allocations ***
            -FUNCTION           CALLS  WORDS  PER CALL  [    %]
            -erlang:apply/2         1      7         7  [ 9.86]
            -lists:seq_loop/3       9     64         7  [90.14]
            -                             71            [100.0]

            The following example prints the combined memory allocation of all +FUNCTION CALLS WORDS PER CALL [ %] +erlang:apply/2 1 7 7 [ 9.86] +lists:seq_loop/3 9 64 7 [90.14] + 71 [100.0]

            The following example prints the combined memory allocation of all processes, sorted by the total number of allocated words in descending -order:

            2> tprof:profile(test, test_spawn, [],
            -                 #{type => call_memory, report => {total, {measurement, descending}}}).
            +order:

            2> tprof:profile(test, test_spawn, [],
            +                 #{type => call_memory, report => {total, {measurement, descending}}}).
             
            -FUNCTION                CALLS  WORDS  PER CALL  [    %]
            -lists:seq_loop/3            9     64         7  [68.82]
            -test:test_spawn/0           1     14        14  [15.05]
            -erlang:apply/2              1      7         7  [ 7.53]
            -erlang:spawn_opt/4          1      6         6  [ 6.45]
            -erlang:spawn_monitor/1      1      2         2  [ 2.15]
            -                                  93            [100.0]

            The profiling data can also be collected for further inspection:

            3> {done, ProfileData} = tprof:profile(fun test:test_spawn/0,
            -                                       #{type => call_memory, report => return}).
            +FUNCTION                CALLS  WORDS  PER CALL  [    %]
            +lists:seq_loop/3            9     64         7  [68.82]
            +test:test_spawn/0           1     14        14  [15.05]
            +erlang:apply/2              1      7         7  [ 7.53]
            +erlang:spawn_opt/4          1      6         6  [ 6.45]
            +erlang:spawn_monitor/1      1      2         2  [ 2.15]
            +                                  93            [100.0]

            The profiling data can also be collected for further inspection:

            3> {done, ProfileData} = tprof:profile(fun test:test_spawn/0,
            +                                       #{type => call_memory, report => return}).
             <...>
            -4> tprof:format(tprof:inspect(ProfileData, process, {percent, descending})).
            +4> tprof:format(tprof:inspect(ProfileData, process, {percent, descending})).
             
             ****** Process <0.223.0>    -- 23.66 % of total allocations ***
            -FUNCTION                CALLS  WORDS  PER CALL  [    %]
            -test:test_spawn/0           1     14        14  [63.64]
            -erlang:spawn_opt/4          1      6         6  [27.27]
            -erlang:spawn_monitor/1      1      2         2  [ 9.09]
            -                                  22            [100.0]
            +FUNCTION                CALLS  WORDS  PER CALL  [    %]
            +test:test_spawn/0           1     14        14  [63.64]
            +erlang:spawn_opt/4          1      6         6  [27.27]
            +erlang:spawn_monitor/1      1      2         2  [ 9.09]
            +                                  22            [100.0]
             
             ****** Process <0.224.0>    -- 76.34 % of total allocations ***
            -FUNCTION           CALLS  WORDS  PER CALL  [    %]
            -lists:seq_loop/3       9     64         7  [90.14]
            -erlang:apply/2         1      7         7  [ 9.86]
            -                             71            [100.0]

            Which processes that are profiled depends on the profiling type.

            • call_count (default) counts calls in all processes.

            • call_time and call_memory limits the profiling to the processes +FUNCTION CALLS WORDS PER CALL [ %] +lists:seq_loop/3 9 64 7 [90.14] +erlang:apply/2 1 7 7 [ 9.86] + 71 [100.0]

            Which processes that are profiled depends on the profiling type.

            • call_count (default) counts calls in all processes.

            • call_time and call_memory limits the profiling to the processes spawned from the user-provided function (using the set_on_spawn -option for trace:process/4).

            call_time and call_memory can be restricted to profile a single process:

            2> tprof:profile(test, test_spawn, [],
            -                 #{type => call_memory, set_on_spawn => false}).
            +option for trace:process/4).

          call_time and call_memory can be restricted to profile a single process:

          2> tprof:profile(test, test_spawn, [],
          +                 #{type => call_memory, set_on_spawn => false}).
           
           ****** Process <0.183.0>    -- 100.00 % of total allocations ***
          -FUNCTION                CALLS  WORDS  PER CALL  [    %]
          -erlang:spawn_monitor/1      1      2         2  [ 9.09]
          -erlang:spawn_opt/4          1      6         6  [27.27]
          -test:test_spawn/0           1     14        14  [63.64]

          Erlang programs can perform expensive operations in other processes +FUNCTION CALLS WORDS PER CALL [ %] +erlang:spawn_monitor/1 1 2 2 [ 9.09] +erlang:spawn_opt/4 1 6 6 [27.27] +test:test_spawn/0 1 14 14 [63.64]

      Erlang programs can perform expensive operations in other processes than the original one. You can include multiple, new, or even all -processes in the trace when measuring time or memory:

      7> pg:start_link().
      -{ok,<0.252.0>}
      -8> tprof:profile(fun() -> pg:join(group, self()) end,
      -                 #href_anchor"ss">type => call_memory, rootset => [pg]}).
      +processes in the trace when measuring time or memory:

      7> pg:start_link().
      +{ok,<0.252.0>}
      +8> tprof:profile(fun() -> pg:join(group, self()) end,
      +                 #href_anchor"ss">type => call_memory, rootset => [pg]}).
       ****** Process <0.252.0>    -- 52.86 % of total allocations ***
      -FUNCTION                      CALLS  WORDS  PER CALL  [    %]
      -pg:leave_local_update_ets/5       1      2         2  [ 1.80]
      -gen:reply/2                       1      3         3  [ 2.70]
      -erlang:monitor/2                  1      3         3  [ 2.70]
      -gen_server:try_handle_call/4      1      3         3  [ 2.70]
      -gen_server:try_dispatch/4         1      3         3  [ 2.70]
      -maps:iterator/1                   2      4         2  [ 3.60]
      -maps:take/2                       1      6         6  [ 5.41]
      -pg:join_local_update_ets/5        1      8         8  [ 7.21]
      -pg:handle_info/2                  1      8         8  [ 7.21]
      -pg:handle_call/3                  1      9         9  [ 8.11]
      -gen_server:loop/7                 2      9         4  [ 8.11]
      -ets:lookup/2                      2     10         5  [ 9.01]
      -pg:join_local/3                   1     11        11  [ 9.91]
      -pg:notify_group/5                 2     16         8  [14.41]
      -erlang:setelement/3               2     16         8  [14.41]
      -                                       111            [100.0]
      +FUNCTION                      CALLS  WORDS  PER CALL  [    %]
      +pg:leave_local_update_ets/5       1      2         2  [ 1.80]
      +gen:reply/2                       1      3         3  [ 2.70]
      +erlang:monitor/2                  1      3         3  [ 2.70]
      +gen_server:try_handle_call/4      1      3         3  [ 2.70]
      +gen_server:try_dispatch/4         1      3         3  [ 2.70]
      +maps:iterator/1                   2      4         2  [ 3.60]
      +maps:take/2                       1      6         6  [ 5.41]
      +pg:join_local_update_ets/5        1      8         8  [ 7.21]
      +pg:handle_info/2                  1      8         8  [ 7.21]
      +pg:handle_call/3                  1      9         9  [ 8.11]
      +gen_server:loop/7                 2      9         4  [ 8.11]
      +ets:lookup/2                      2     10         5  [ 9.01]
      +pg:join_local/3                   1     11        11  [ 9.91]
      +pg:notify_group/5                 2     16         8  [14.41]
      +erlang:setelement/3               2     16         8  [14.41]
      +                                       111            [100.0]
       
       ****** Process <0.255.0>    -- 47.14 % of total allocations ***
      -FUNCTION                   CALLS  WORDS  PER CALL  [    %]
      -erl_eval:match_list/6          1      3         3  [ 3.03]
      -erlang:monitor/2               1      3         3  [ 3.03]
      -lists:reverse/1                2      4         2  [ 4.04]
      /usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/xref_chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (993))
      --- old//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/xref_chapter.html	2026-08-21 04:00:32.197377914 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/tools-4.1.4/doc/html/xref_chapter.html	2026-08-21 04:00:32.197377914 +0000
      @@ -98,25 +98,25 @@
       system and for doing some simple graph analyses on selected calls.

      The following sections show some features of Xref, beginning with a module check and a predefined analysis. Then follow examples that can be skipped on the first reading; not all of the concepts used are explained, and it is assumed that the -reference manual has been at least skimmed.

      Module Check

      Assume we want to check the following module:

      -module(my_module).
      +reference manual has been at least skimmed.

      Module Check

      Assume we want to check the following module:

      -module(my_module).
       
      --export([t/1]).
      +-export([t/1]).
       
      -t(A) ->
      -  my_module:t2(A).
      +t(A) ->
      +  my_module:t2(A).
       
      -t2(_) ->
      +t2(_) ->
         true.

      Cross reference data are read from BEAM files, so the first step when checking -an edited module is to compile it:

      1> c(my_module, debug_info).
      +an edited module is to compile it:

      1> c(my_module, debug_info).
       ./my_module.erl:10: Warning: function t2/1 is unused
      -{ok, my_module}

      The debug_info option ensures that the BEAM file contains debug information, +{ok, my_module}

      The debug_info option ensures that the BEAM file contains debug information, which makes it possible to find unused local functions.

      The module can now be checked for calls to deprecated functions, calls to undefined functions, and for unused local -functions:

      2> xref:m(my_module)
      -[{deprecated,[]},
      - {undefined,[{{my_module,t,1},{my_module,t2,1}}]},
      - {unused,[{my_module,t2,1}]}]

      m/1 is also suitable for checking that the BEAM file of a module that is about +functions:

      2> xref:m(my_module)
      +[{deprecated,[]},
      + {undefined,[{{my_module,t,1},{my_module,t2,1}}]},
      + {unused,[{my_module,t2,1}]}]

      m/1 is also suitable for checking that the BEAM file of a module that is about to be loaded into a running a system does not call any undefined functions. In either case, the code path of the code server (see the module code) is used for finding modules that export externally called functions not exported by the @@ -125,28 +125,28 @@ this example an xref server will be used, which makes it possible to analyze applications and releases, and also to select the library path explicitly.

      Each Xref server is referred to by a unique name. The name is given when -creating the server:

      1> xref:start(s).
      -{ok,<0.27.0>}

      Next the system to be analyzed is added to the Xref server. Here the system will +creating the server:

      1> xref:start(s).
      +{ok,<0.27.0>}

      Next the system to be analyzed is added to the Xref server. Here the system will be OTP, so no library path will be needed. Otherwise, when analyzing a system that uses OTP, the OTP modules are typically made library modules by setting the library path to the default OTP code path (or to code_path, see the reference manual). By default, the names of read BEAM files and warnings are output when adding analyzed modules, but these messages -can be avoided by setting default values of some options:

      2> xref:set_default(s, [{verbose,false}, {warnings,false}]).
      +can be avoided by setting default values of some options:

      2> xref:set_default(s, [{verbose,false}, {warnings,false}]).
       ok
      -3> xref:add_release(s, code:lib_dir(), {name, otp}).
      -{ok,otp}

      add_release/3 assumes that all subdirectories of the library directory +3> xref:add_release(s, code:lib_dir(), {name, otp}). +{ok,otp}

      add_release/3 assumes that all subdirectories of the library directory returned by code:lib_dir() contain applications; -the effect is that of reading all BEAM files for the application.

      It is now easy to check the release for calls to undefined functions:

      4> xref:analyze(s, undefined_function_calls).
      -{ok, [...]}

      We can now continue with further analyses, or we can delete the Xref server:

      5> xref:stop(s).

      The check for calls to undefined functions is an example of a predefined +the effect is that of reading all BEAM files for the application.

      It is now easy to check the release for calls to undefined functions:

      4> xref:analyze(s, undefined_function_calls).
      +{ok, [...]}

      We can now continue with further analyses, or we can delete the Xref server:

      5> xref:stop(s).

      The check for calls to undefined functions is an example of a predefined analysis, probably the most useful one. Other examples are the analyses that find unused local functions, or functions that call some given functions. See the analyze/2,3 functions for a complete list of predefined analyses.

      Each predefined analysis is a shorthand for a query, a sentence of a tiny language providing cross reference data as values of predefined variables. The check for calls to -undefined functions can thus be stated as a query:

      4> xref:q(s, "(XC - UC) || (XU - X - B)").
      -{ok,[...]}

      The query asks for the restriction of external calls except the unresolved calls +undefined functions can thus be stated as a query:

      4> xref:q(s, "(XC - UC) || (XU - X - B)").
      +{ok,[...]}

      The query asks for the restriction of external calls except the unresolved calls to calls to functions that are externally used but neither exported nor built-in functions (the || operator restricts the used functions while the | operator restricts the calling functions). The - operator returns the difference of two @@ -170,8 +170,8 @@ provided with a simple language. Below are some expressions of the language with comments, focusing on elements of the language rather than providing useful examples. The analyzed system is assumed to be OTP, so in order to run the -queries, first evaluate these calls:

      xref:start(s).
      -xref:add_release(s, code:root_dir()).
      • xref:q(s, "(Fun) xref : Mod"). - All functions of the xref module.

      • xref:q(s, "xref : Mod * X"). - All exported functions of the xref +queries, first evaluate these calls:

        xref:start(s).
        +xref:add_release(s, code:root_dir()).
        • xref:q(s, "(Fun) xref : Mod"). - All functions of the xref module.

        • xref:q(s, "xref : Mod * X"). - All exported functions of the xref module. The first operand of the intersection operator * is implicitly converted to the more special type of the second operand.

        • xref:q(s, "(Mod) tools"). - All modules of the Tools application.

        • xref:q(s, '"xref_.*" : Mod'). - All modules with a name beginning with xref_.

        • xref:q(s, "# E | X "). - Number of calls from exported functions.

        • xref:q(s, "XC || L "). - All external calls to local functions.

        • xref:q(s, "XC * LC"). - All calls that have both an external and a local @@ -208,18 +208,18 @@ a module M1 is said to call a module M2 if there is some function in M1 that calls some function in M2. It would be nice if we could use the much smaller module graph, since it is available also in the light weight -modulesmode of Xref servers.

          t(S) ->
          -  {ok, _} = xref:q(S, "Eplus := closure E"),
          -  {ok, Ms} = xref:q(S, "AM"),
          -  Fun = fun(M, N) ->
          -      Q = io_lib:format("# (Mod) (Eplus | ~p : Mod)", [M]),
          -      {ok, N0} = xref:q(S, lists:flatten(Q)),
          +modulesmode of Xref servers.

          t(S) ->
          +  {ok, _} = xref:q(S, "Eplus := closure E"),
          +  {ok, Ms} = xref:q(S, "AM"),
          +  Fun = fun(M, N) ->
          +      Q = io_lib:format("# (Mod) (Eplus | ~p : Mod)", [M]),
          +      {ok, N0} = xref:q(S, lists:flatten(Q)),
                 N + N0
               end,
          -  Sum = lists:foldl(Fun, 0, Ms),
          -  ok = xref:forget(S, 'Eplus'),
          -  {ok, Tot} = xref:q(S, "# (closure ME | AM)"),
          -  100 * ((Tot - Sum) / Tot).

          Comments on the code:

          • We want to find the reduction of the closure of the function graph to modules. + Sum = lists:foldl(Fun, 0, Ms), + ok = xref:forget(S, 'Eplus'), + {ok, Tot} = xref:q(S, "# (closure ME | AM)"), + 100 * ((Tot - Sum) / Tot).

          Comments on the code:

          • We want to find the reduction of the closure of the function graph to modules. The direct expression for doing that would be (Mod) (closure E | AM), but then we would have to represent all of the transitive closure of E in memory. Instead the number of indirectly used modules is found for each analyzed /usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/chapter.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (839)) --- old//usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/chapter.html 2026-08-21 04:00:32.214378025 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/chapter.html 2026-08-21 04:00:32.214378025 +0000 @@ -113,13 +113,13 @@ is the object reference. Optional arguments are last and expressed as tagged tuples in any order.

            For example the wxWindow C++ class is implemented in the wxWindow erlang module and the member wxWindow::CenterOnParent is thus -wxWindow:centerOnParent. The following C++ code:

              wxWindow MyWin = new wxWindow();
            -  MyWin.CenterOnParent(wxVERTICAL);
            +wxWindow:centerOnParent. The following C++ code:

              wxWindow MyWin = new wxWindow();
            +  MyWin.CenterOnParent(wxVERTICAL);
               ...
            -  delete MyWin;

            would in erlang look like:

              MyWin = wxWindow:new(),
            -  wxWindow:centerOnParent(MyWin, [{dir,?wxVERTICAL}]),
            +  delete MyWin;

            would in erlang look like:

              MyWin = wxWindow:new(),
            +  wxWindow:centerOnParent(MyWin, [{dir,?wxVERTICAL}]),
               ...
            -  wxWindow:destroy(MyWin),

            When you are reading wxWidgets documentation or the examples, you will notice + wxWindow:destroy(MyWin),

            When you are reading wxWidgets documentation or the examples, you will notice that some of the most basic classes are missing in wx, they are directly mapped to corresponding erlang terms:

            • wxPoint is represented by {Xcoord,Ycoord}

            • wxSize is represented by {Width,Height}

            • wxRect is represented by {Xcoord,Ycoord,Width,Height}

            • wxColour is represented by {Red,Green,Blue[,Alpha]}

            • wxString is represented by unicode:charlist()

            • wxGBPosition is represented by {Row,Column}

            • wxGBSpan is represented by {RowSpan,ColumnSPan}

            • wxGridCellCoords is represented by {Row,Column}

            In the places where the erlang API differs from the original one it should be @@ -141,14 +141,14 @@ from several processes in your application, you must share the environment. You can get the active environment with wx:get_env/0 and set it in the new processes with wx:set_env/1. Two processes or applications which have both -called wx:new() will not be able use each others objects.

              wx:new(),
            -  MyWin = wxFrame:new(wx:null(), 42, "Example", []),
            -  Env = wx:get_env(),
            -  spawn(fun() ->
            -           wx:set_env(Env),
            +called wx:new() will not be able use each others objects.

              wx:new(),
            +  MyWin = wxFrame:new(wx:null(), 42, "Example", []),
            +  Env = wx:get_env(),
            +  spawn(fun() ->
            +           wx:set_env(Env),
                        %% Here you can do wx calls from your helper process.
                        ...
            -        end),
            +        end),
               ...

            When wx:destroy/0 is invoked or when all processes in the application have died, the memory is deleted and all windows created by that application are closed.

            The wx application never cleans or garbage collects memory as long as the user /usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx.epub/OEBPS/chapter.xhtml differs (HTML document, ASCII text, with very long lines (839)) --- old//usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx.epub/OEBPS/chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx.epub/OEBPS/chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -41,13 +41,13 @@ is the object reference. Optional arguments are last and expressed as tagged tuples in any order.

            For example the wxWindow C++ class is implemented in the wxWindow erlang module and the member wxWindow::CenterOnParent is thus -wxWindow:centerOnParent. The following C++ code:

              wxWindow MyWin = new wxWindow();
            -  MyWin.CenterOnParent(wxVERTICAL);
            +wxWindow:centerOnParent. The following C++ code:

              wxWindow MyWin = new wxWindow();
            +  MyWin.CenterOnParent(wxVERTICAL);
               ...
            -  delete MyWin;

            would in erlang look like:

              MyWin = wxWindow:new(),
            -  wxWindow:centerOnParent(MyWin, [{dir,?wxVERTICAL}]),
            +  delete MyWin;

            would in erlang look like:

              MyWin = wxWindow:new(),
            +  wxWindow:centerOnParent(MyWin, [{dir,?wxVERTICAL}]),
               ...
            -  wxWindow:destroy(MyWin),

            When you are reading wxWidgets documentation or the examples, you will notice + wxWindow:destroy(MyWin),

            When you are reading wxWidgets documentation or the examples, you will notice that some of the most basic classes are missing in wx, they are directly mapped to corresponding erlang terms:

            • wxPoint is represented by {Xcoord,Ycoord}

            • wxSize is represented by {Width,Height}

            • wxRect is represented by {Xcoord,Ycoord,Width,Height}

            • wxColour is represented by {Red,Green,Blue[,Alpha]}

            • wxString is represented by unicode:charlist()

            • wxGBPosition is represented by {Row,Column}

            • wxGBSpan is represented by {RowSpan,ColumnSPan}

            • wxGridCellCoords is represented by {Row,Column}

            In the places where the erlang API differs from the original one it should be @@ -69,14 +69,14 @@ from several processes in your application, you must share the environment. You can get the active environment with wx:get_env/0 and set it in the new processes with wx:set_env/1. Two processes or applications which have both -called wx:new() will not be able use each others objects.

              wx:new(),
            -  MyWin = wxFrame:new(wx:null(), 42, "Example", []),
            -  Env = wx:get_env(),
            -  spawn(fun() ->
            -           wx:set_env(Env),
            +called wx:new() will not be able use each others objects.

              wx:new(),
            +  MyWin = wxFrame:new(wx:null(), 42, "Example", []),
            +  Env = wx:get_env(),
            +  spawn(fun() ->
            +           wx:set_env(Env),
                        %% Here you can do wx calls from your helper process.
                        ...
            -        end),
            +        end),
               ...

            When wx:destroy/0 is invoked or when all processes in the application have died, the memory is deleted and all windows created by that application are closed.

            The wx application never cleans or garbage collects memory as long as the user /usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx.epub/OEBPS/content.opf differs (XML 1.0 document, ASCII text) --- old//usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx.epub/OEBPS/content.opf 2026-08-05 05:56:49.000000000 +0000 @@ -4,10 +4,10 @@ version="3.0"> wx - 2.5.4.1 - urn:uuid:16df6140-82d6-2ae8-662a-8cec469a317d + urn:uuid:5d3b8a36-18d0-9377-30aa-1be226d05749 en - 2026-08-21T03:48:32Z + 2042-09-22T17:07:21Z /usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx.epub/OEBPS/wx_object.xhtml differs (HTML document, ASCII text, with very long lines (722)) --- old//usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx.epub/OEBPS/wx_object.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx.epub/OEBPS/wx_object.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -30,36 +30,36 @@ shutdown | Term, terminate(State) is called. It lets the user module clean up, it is always called when server terminates or when wx_object() in the driver is deleted. If the Parent process terminates the Module:terminate/2 function is -called.
            terminate(Reason, State)

            Example:

              -module(myDialog).
            -  -export([new/2, show/1, destroy/1]).  %% API
            -  -export([init/1, handle_call/3, handle_event/2,
            -           handle_info/2, code_change/3, terminate/2]).
            +called.
            terminate(Reason, State)

            Example:

              -module(myDialog).
            +  -export([new/2, show/1, destroy/1]).  %% API
            +  -export([init/1, handle_call/3, handle_event/2,
            +           handle_info/2, code_change/3, terminate/2]).
                        new/2, showModal/1, destroy/1]).  %% Callbacks
             
               %% Client API
            -  new(Parent, Msg) ->
            -     wx_object:start(?MODULE, [Parent,Id], []).
            +  new(Parent, Msg) ->
            +     wx_object:start(?MODULE, [Parent,Id], []).
             
            -  show(Dialog) ->
            -     wx_object:call(Dialog, show_modal).
            +  show(Dialog) ->
            +     wx_object:call(Dialog, show_modal).
             
            -  destroy(Dialog) ->
            -     wx_object:call(Dialog, destroy).
            +  destroy(Dialog) ->
            +     wx_object:call(Dialog, destroy).
             
               %% Server Implementation ala gen_server
            -  init([Parent, Str]) ->
            -     Dialog = wxDialog:new(Parent, 42, "Testing", []),
            +  init([Parent, Str]) ->
            +     Dialog = wxDialog:new(Parent, 42, "Testing", []),
                  ...
            -     wxDialog:connect(Dialog, command_button_clicked),
            -     {Dialog, MyState}.
            +     wxDialog:connect(Dialog, command_button_clicked),
            +     {Dialog, MyState}.
             
            -  handle_call(show, _From, State) ->
            -     wxDialog:show(State#state.win),
            -     {reply, ok, State};
            +  handle_call(show, _From, State) ->
            +     wxDialog:show(State#state.win),
            +     {reply, ok, State};
               ...
            -  handle_event(#wx{}, State) ->
            -     io:format("Users clicked button~n",[]),
            -     {noreply, State};
            +  handle_event(#wx{}, State) ->
            +     io:format("Users clicked button~n",[]),
            +     {noreply, State};
               ...

            DATA TYPES

            /usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx_object.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx_object.html 2026-08-21 04:00:32.831382041 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/wx-2.5.4.1/doc/html/wx_object.html 2026-08-21 04:00:32.831382041 +0000 @@ -101,36 +101,36 @@ shutdown | Term, terminate(State) is called. It lets the user module clean up, it is always called when server terminates or when wx_object() in the driver is deleted. If the Parent process terminates the Module:terminate/2 function is -called.
            terminate(Reason, State)

            Example:

              -module(myDialog).
            -  -export([new/2, show/1, destroy/1]).  %% API
            -  -export([init/1, handle_call/3, handle_event/2,
            -           handle_info/2, code_change/3, terminate/2]).
            +called.
            terminate(Reason, State)

            Example:

              -module(myDialog).
            +  -export([new/2, show/1, destroy/1]).  %% API
            +  -export([init/1, handle_call/3, handle_event/2,
            +           handle_info/2, code_change/3, terminate/2]).
                        new/2, showModal/1, destroy/1]).  %% Callbacks
             
               %% Client API
            -  new(Parent, Msg) ->
            -     wx_object:start(?MODULE, [Parent,Id], []).
            +  new(Parent, Msg) ->
            +     wx_object:start(?MODULE, [Parent,Id], []).
             
            -  show(Dialog) ->
            -     wx_object:call(Dialog, show_modal).
            +  show(Dialog) ->
            +     wx_object:call(Dialog, show_modal).
             
            -  destroy(Dialog) ->
            -     wx_object:call(Dialog, destroy).
            +  destroy(Dialog) ->
            +     wx_object:call(Dialog, destroy).
             
               %% Server Implementation ala gen_server
            -  init([Parent, Str]) ->
            -     Dialog = wxDialog:new(Parent, 42, "Testing", []),
            +  init([Parent, Str]) ->
            +     Dialog = wxDialog:new(Parent, 42, "Testing", []),
                  ...
            -     wxDialog:connect(Dialog, command_button_clicked),
            -     {Dialog, MyState}.
            +     wxDialog:connect(Dialog, command_button_clicked),
            +     {Dialog, MyState}.
             
            -  handle_call(show, _From, State) ->
            -     wxDialog:show(State#state.win),
            -     {reply, ok, State};
            +  handle_call(show, _From, State) ->
            +     wxDialog:show(State#state.win),
            +     {reply, ok, State};
               ...
            -  handle_event(#wx{}, State) ->
            -     io:format("Users clicked button~n",[]),
            -     {noreply, State};
            +  handle_event(#wx{}, State) ->
            +     io:format("Users clicked button~n",[]),
            +     {noreply, State};
               ...

            DATA TYPES

            /usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_examples.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (2073)) --- old//usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_examples.html 2026-08-21 04:00:32.852382178 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_examples.html 2026-08-21 04:00:32.852382178 +0000 @@ -104,86 +104,86 @@ user state, use their own state variable instead. Another option (used in e.g. xmerl_eventp.erl) is for customization functions to share one of the local states (in xmerl_eventp.erl, the continuation function and the fetch function -both access the cont_state.)

            Functions to access user state:

            • xmerl_scan:user_state(GlobalState)
            • xmerl_scan:user_state(UserState, GlobalState)

            1.2 Event Function

            {event_fun, fun()} | {event_fun, fun(), EventState}

            The event function is called at the beginning and at the end of a parsed entity. -It has the following format and semantics:

            fun(Event, GlobalState) ->
            -   EventState = xmerl_scan:event_state(GlobalState),
            -   EventState2 = foo(Event, EventState),
            -   GlobalState2 = xmerl_scan:event_state(EventState2, GlobalState)
            -end.

            1.3 Hook Function

            {hook_fun, fun()} | {hook_fun, fun(), HookState}

            The hook function is called when the processor has parsed a complete entity. -Format and semantics:

            fun(Entity, GlobalState) ->
            -   HookState = xmerl_scan:hook_state(GlobalState),
            -   {TransformedEntity, HookState2} = foo(Entity, HookState),
            -   GlobalState2 = xmerl_scan:hook_state(HookState2, GlobalState),
            -   {TransformedEntity, GlobalState2}
            +both access the cont_state.)

            Functions to access user state:

            • xmerl_scan:user_state(GlobalState)
            • xmerl_scan:user_state(UserState, GlobalState)

            1.2 Event Function

            {event_fun, fun()} | {event_fun, fun(), EventState}

            The event function is called at the beginning and at the end of a parsed entity. +It has the following format and semantics:

            fun(Event, GlobalState) ->
            +   EventState = xmerl_scan:event_state(GlobalState),
            +   EventState2 = foo(Event, EventState),
            +   GlobalState2 = xmerl_scan:event_state(EventState2, GlobalState)
            +end.

            1.3 Hook Function

            {hook_fun, fun()} | {hook_fun, fun(), HookState}

            The hook function is called when the processor has parsed a complete entity. +Format and semantics:

            fun(Entity, GlobalState) ->
            +   HookState = xmerl_scan:hook_state(GlobalState),
            +   {TransformedEntity, HookState2} = foo(Entity, HookState),
            +   GlobalState2 = xmerl_scan:hook_state(HookState2, GlobalState),
            +   {TransformedEntity, GlobalState2}
             end.

            The relationship between the event function, the hook function and the accumulator function is as follows:

            1. The event function is first called with an 'ended' event for the parsed entity.
            2. The hook function is called, possibly re-formatting the entity.
            3. The acc function is called in order to (optionally) add the re-formatted -entity to the contents of its parent element.

            1.4 Fetch Function

            {fetch_fun, fun()} | {fetch_fun, fun(), FetchState}

            The fetch function is called in order to fetch an external resource (e.g. a +entity to the contents of its parent element.

          • 1.4 Fetch Function

            {fetch_fun, fun()} | {fetch_fun, fun(), FetchState}

            The fetch function is called in order to fetch an external resource (e.g. a DTD).

            The fetch function can respond with three different return values:

            Result ::=
            -   {ok, {file, Filename}, NewGlobalState} |
            -   {ok, {string, String}, NewGlobalState} |
            -   {ok, not_fetched, NewGlobalState}

            Format and semantics:

            fun(URI, GlobalState) ->
            -   FetchState = xmerl_scan:fetch_state(GlobalState),
            -   Result = foo(URI, FetchState).  % Result being one of the above
            -end.

            1.5 Continuation Function

            {continuation_fun, fun()} | {continuation_fun, fun(), ContinuationState}

            The continuation function is called when the parser encounters the end of the -byte stream. Format and semantics:

            fun(Continue, Exception, GlobalState) ->
            -   ContState = xmerl_scan:cont_state(GlobalState),
            -   {Result, ContState2} = get_more_bytes(ContState),
            +   {ok, {file, Filename}, NewGlobalState} |
            +   {ok, {string, String}, NewGlobalState} |
            +   {ok, not_fetched, NewGlobalState}

            Format and semantics:

            fun(URI, GlobalState) ->
            +   FetchState = xmerl_scan:fetch_state(GlobalState),
            +   Result = foo(URI, FetchState).  % Result being one of the above
            +end.

            1.5 Continuation Function

            {continuation_fun, fun()} | {continuation_fun, fun(), ContinuationState}

            The continuation function is called when the parser encounters the end of the +byte stream. Format and semantics:

            fun(Continue, Exception, GlobalState) ->
            +   ContState = xmerl_scan:cont_state(GlobalState),
            +   {Result, ContState2} = get_more_bytes(ContState),
                case Result of
            -      [] ->
            -         GlobalState2 = xmerl_scan:cont_state(ContState2, GlobalState),
            -         Exception(GlobalState2);
            +      [] ->
            +         GlobalState2 = xmerl_scan:cont_state(ContState2, GlobalState),
            +         Exception(GlobalState2);
                   MoreBytes ->
            -         {MoreBytes2, Rest} = end_on_whitespace_char(MoreBytes),
            -         ContState3 = update_cont_state(Rest, ContState2),
            -         GlobalState3 = xmerl_scan:cont_state(ContState3, GlobalState),
            -         Continue(MoreBytes2, GlobalState3)
            +         {MoreBytes2, Rest} = end_on_whitespace_char(MoreBytes),
            +         ContState3 = update_cont_state(Rest, ContState2),
            +         GlobalState3 = xmerl_scan:cont_state(ContState3, GlobalState),
            +         Continue(MoreBytes2, GlobalState3)
                end
            -end.

            1.6 Rules Functions

            {rules, ReadFun : fun(), WriteFun : fun(), RulesState} |
            -{rules, Table : ets()}

            The rules functions take care of storing scanner information in a rules +end.

      1.6 Rules Functions

      {rules, ReadFun : fun(), WriteFun : fun(), RulesState} |
      +{rules, Table : ets()}

      The rules functions take care of storing scanner information in a rules database. User-provided rules functions may opt to store the information in mnesia, or perhaps in the user_state(RulesState).

      The following modes exist:

      • If the user doesn't specify an option, the scanner creates an ets table, and uses built-in functions to read and write data to it. When the scanner is done, the ets table is deleted.
      • If the user specifies an ets table via the {rules, Table} option, the scanner uses this table. When the scanner is done, it does not delete the table.
      • If the user specifies read and write functions, the scanner will use them -instead.

      The format for the read and write functions are as follows:

       WriteFun(Context, Name, Definition, ScannerState) -> NewScannerState.
      - ReadFun(Context, Name, ScannerState) -> Definition | undefined.

      Here is a summary of the data objects currently being written by the scanner:

      ContextKey ValueDefinition
      notationNotationName{system, SL} | {public, PIDL, SL}
      elem_defElementName#xmlElement{content = ContentSpec}
      parameter_entityPENamePEDef
      entityEntityNameEntityDef

      Table 1: Scanner data objects

      where

      ContentSpec ::= empty | any | ElemContent
      -ElemContent ::= {Mode, Elems}
      +instead.

    The format for the read and write functions are as follows:

     WriteFun(Context, Name, Definition, ScannerState) -> NewScannerState.
    + ReadFun(Context, Name, ScannerState) -> Definition | undefined.

    Here is a summary of the data objects currently being written by the scanner:

    ContextKey ValueDefinition
    notationNotationName{system, SL} | {public, PIDL, SL}
    elem_defElementName#xmlElement{content = ContentSpec}
    parameter_entityPENamePEDef
    entityEntityNameEntityDef

    Table 1: Scanner data objects

    where

    ContentSpec ::= empty | any | ElemContent
    +ElemContent ::= {Mode, Elems}
     Mode        ::= seq | choice
    -Elems       ::= [Elem]
    -Elem        ::= '#PCDATA' | Name | ElemContent | {Occurrence, Elems}
    +Elems       ::= [Elem]
    +Elem        ::= '#PCDATA' | Name | ElemContent | {Occurrence, Elems}
     Occurrence  ::= '*' | '?' | '+'

    NOTE: When <Elem> is not wrapped with <Occurrence>, (Occurrence = once) is -implied.

    1.7 Accumulator Function

    {acc_fun, fun()}

    The accumulator function is called to accumulate the contents of an entity.When +implied.

    1.7 Accumulator Function

    {acc_fun, fun()}

    The accumulator function is called to accumulate the contents of an entity.When parsing very large files, it may not be desirable to do so.In this case, an acc function can be provided that simply doesn't accumulate.

    Note that it is possible to even modify the parsed entity before accumulating it, but this must be done with care. xmerl_scan performs post-processing of the element for namespace management. Thus, the element must keep its original structure for this to work.

    The acc function has the following format and semantics:

    %% default accumulating acc fun
    -fun(ParsedEntity, Acc, GlobalState) ->
    -   {[ParsedEntity|Acc], GlobalState}.
    +fun(ParsedEntity, Acc, GlobalState) ->
    +   {[ParsedEntity|Acc], GlobalState}.
     
     %% non-accumulating acc fun
    -fun(ParsedEntity, Acc, GlobalState) ->
    -   {Acc, GlobalState}.

    1.8 Close Function

    The close function is called when a document (either the main document or an +fun(ParsedEntity, Acc, GlobalState) -> + {Acc, GlobalState}.

    1.8 Close Function

    The close function is called when a document (either the main document or an external DTD) has been completely parsed. When xmerl_scan was started using xmerl_scan:file/[1,2], the file will be read in full, and closed immediately, before the parsing starts, so when the close function is called, it will not need to actually close the file. In this case, the close function will be a good -place to modify the state variables.

    Format and semantics:

    fun(GlobalState) ->
    -   GlobalState1 = ....  % state variables may be altered

    2 Examples

    See xmerl_test.erl for more examples.

    2.1 Handling spaces

    The following sample program illustrates three ways of scanning a document:

    1. the default scan, which leaves whitespace untouched
    2. normalizing spaces
    3. normalizing spaces, then removing text elements that only contain one space.
    -module(tmp).
    +place to modify the state variables.

    Format and semantics:

    fun(GlobalState) ->
    +   GlobalState1 = ....  % state variables may be altered

    2 Examples

    See xmerl_test.erl for more examples.

    2.1 Handling spaces

    The following sample program illustrates three ways of scanning a document:

    1. the default scan, which leaves whitespace untouched
    2. normalizing spaces
    3. normalizing spaces, then removing text elements that only contain one space.
    -module(tmp).
     
    --include("xmerl.hrl").
    +-include("xmerl.hrl").
     
    --export([file1/1, file2/1, file3/1]).
    +-export([file1/1, file2/1, file3/1]).
     
    -file1(F) -> xmerl_scan:file(F).
    +file1(F) -> xmerl_scan:file(F).
     
    -file2(F) -> xmerl_scan:file(F, [{space,normalize}]).
    +file2(F) -> xmerl_scan:file(F, [{space,normalize}]).
     
    -file3(F) -> Acc = fun(#xmlText{value = " ", pos = P}, Acc, S) -> {Acc, P,
    -S}; % new return format (X, Acc, S) -> {[X|Acc], S} end, xmerl_scan:file(F,
    -[{space,normalize}, {acc_fun, Acc}]).
    +
    file3(F) -> Acc = fun(#xmlText{value = " ", pos = P}, Acc, S) -> {Acc, P, +S}; % new return format (X, Acc, S) -> {[X|Acc], S} end, xmerl_scan:file(F, +[{space,normalize}, {acc_fun, Acc}]).
    /usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_ug.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1168)) --- old//usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_ug.html 2026-08-21 04:00:32.876382334 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_ug.html 2026-08-21 04:00:32.876382334 +0000 @@ -133,16 +133,16 @@ structure and data of the document. If it is a simple document like:

    <?xml version="1.0"?>
     <dog>
     Grand Danois
    -</dog>

    The parse result will be:

    #xmlElement{name = dog,
    +</dog>

    The parse result will be:

    #xmlElement{name = dog,
                 ...
    -            parents = [],
    +            parents = [],
                 ...
    -            attributes = [],
    -            content = [{xmlText,[{dog,1}],1,[],"\
    +            attributes = [],
    +            content = [{xmlText,[{dog,1}],1,[],"\
     Grand Danois\
    -",text}],
    +",text}],
                 ...
    -            }

    Where the content of the top element is: + }

    Where the content of the top element is: [{xmlText,[{dog,1}],1,[],"\ Grand Danois\ ",text}]. Text will be returned in xmlText records. Though, usually documents are more complex, and the content of the top element will in that case be a nested structure with #xmlElement{} @@ -184,41 +184,41 @@ <!ELEMENT motorcycles (bike,date?)+ > <!ELEMENT bike (name,engine,kind,drive, accessories?,comment?) > <!ELEMENT name (manufacturer,brandName,additionalName?) > -<!ELEMENT manufacturer (#href_anchor"makeup erlang" translate="no">3> {ParseResult,Misc}=xmerl_scan:file("motorcycles.xml"). -{{xmlElement,motorcycles, +<!ELEMENT manufacturer (#href_anchor"makeup erlang" translate="no">3> {ParseResult,Misc}=xmerl_scan:file("motorcycles.xml"). +{{xmlElement,motorcycles, motorcycles, - [], - {xmlNamespace,[],[]}, - [], + [], + {xmlNamespace,[],[]}, + [], 1, - [], - [{xmlText,[{motorcycles,1}],1,[],"\ - ",text}, - {xmlElement,bike, + [], + [{xmlText,[{motorcycles,1}],1,[],"\ + ",text}, + {xmlElement,bike, bike, - [], - {xmlNamespace,[],[]}, - [{motorcycles,1}], + [], + {xmlNamespace,[],[]}, + [{motorcycles,1}], 2, - [{xmlAttribute,year,[],[],[],[]|...}, - {xmlAttribute,color,[],[],[]|...}], - [{xmlText,[{bike,2},{motorcycles|...}], + [{xmlAttribute,year,[],[],[],[]|...}, + {xmlAttribute,color,[],[],[]|...}], + [{xmlText,[{bike,2},{motorcycles|...}], 1, - []|...}, - {xmlElement,name,name,[]|...}, - {xmlText,[{...}|...],3|...}, - {xmlElement,engine|...}, - {xmlText|...}, - {...}|...], - [], + []|...}, + {xmlElement,name,name,[]|...}, + {xmlText,[{...}|...],3|...}, + {xmlElement,engine|...}, + {xmlText|...}, + {...}|...], + [], ".", - undeclared}, + undeclared}, ... - ], - [], + ], + [], ".", - undeclared}, - []} + undeclared}, + []} 4>

    If you instead receives the XML doc as a string you can parse it by xmerl_scan:string/1. Both file/2 and string/2 exists where the second argument is a list of options to the parser, see the reference manual.

    Example: Extracting Data From XML Content

    In this example consider the situation where you want to examine a particular @@ -243,22 +243,22 @@ {Tag, Content} or Tag where:

    • Tag = atom()
    • Attributes = [{Name, Value}| #xmlAttribute{}]
    • Name = atom()
    • Value = IOString | atom() | integer()

    See also reference manual for xmerl

    If you want to add the information about a black Harley Davidsson 1200 cc Sportster motorcycle from 2003 that is in shape as new in the motorcycles.xml document you can put the data in a simple-form data structure like:

    Data =
    -  {bike,
    -     [{year,"2003"},{color,"black"},{condition,"new"}],
    -     [{name,
    -         [{manufacturer,["Harley Davidsson"]},
    -          {brandName,["XL1200C"]},
    -          {additionalName,["Sportster"]}]},
    -      {engine,
    -         ["V-engine, 2-cylinders, 1200 cc"]},
    -      {kind,["custom"]},
    -      {drive,["belt"]}]}

    In order to append this data to the end of the motorcycles.xml document you have -to parse the file and add Data to the end of the root element content.

        {RootEl,Misc}=xmerl_scan:file('motorcycles.xml'),
    -    #xmlElement{content=Content} = RootEl,
    -    NewContent=Content++lists:flatten([Data]),
    -    NewRootEl=RootEl#xmlElement{content=NewContent},

    Then you can run it through the export_simple/2 function:

        {ok,IOF}=file:open('new_motorcycles.xml',[write]),
    -    Export=xmerl:export_simple([NewRootEl],xmerl_xml),
    -    io:format(IOF,"~s~n",[lists:flatten(Export)]),

    The result would be:

    
    +  {bike,
    +     [{year,"2003"},{color,"black"},{condition,"new"}],
    +     [{name,
    +         [{manufacturer,["Harley Davidsson"]},
    +          {brandName,["XL1200C"]},
    +          {additionalName,["Sportster"]}]},
    +      {engine,
    +         ["V-engine, 2-cylinders, 1200 cc"]},
    +      {kind,["custom"]},
    +      {drive,["belt"]}]}

    In order to append this data to the end of the motorcycles.xml document you have +to parse the file and add Data to the end of the root element content.

        {RootEl,Misc}=xmerl_scan:file('motorcycles.xml'),
    +    #xmlElement{content=Content} = RootEl,
    +    NewContent=Content++lists:flatten([Data]),
    +    NewRootEl=RootEl#xmlElement{content=NewContent},

    Then you can run it through the export_simple/2 function:

        {ok,IOF}=file:open('new_motorcycles.xml',[write]),
    +    Export=xmerl:export_simple([NewRootEl],xmerl_xml),
    +    io:format(IOF,"~s~n",[lists:flatten(Export)]),

    The result would be:

    
     <?xml version="1.0"?><motorcycles>
       <bike year="2000" color="black">
         <name>
    @@ -285,40 +285,40 @@
     <bike year="2003" color="black" condition="new"><name><manufacturer>Harley Davidsson</manufacturer><brandName>XL1200C</brandName><additionalName>Sportster</additionalName></name><engine>V-engine, 2-cylinders, 1200 cc</engine><kind>custom</kind><drive>belt</drive></bike></motorcycles>

    If it is important to get similar indentation and newlines as in the original document you have to add #href_anchor"inline">{prolog,Value} to export_simple/3. The following example code fixes those changes in the previous example:

        Data =
    -      [#xmlText{value="  "},
    -       {bike,[{year,"2003"},{color,"black"},{condition,"new"}],
    -             [#xmlText{value="\
    -    "},
    -              {name,[#xmlText{value="\
    -      "},
    -                     {manufacturer,["Harley Davidsson"]},
    -                     #xmlText{value="\
    -      "},
    -                     {brandName,["XL1200C"]},
    -                     #xmlText{value="\
    -      "},
    -                     {additionalName,["Sportster"]},
    -                     #xmlText{value="\
    -    "}]},
    -              {engine,["V-engine, 2-cylinders, 1200 cc"]},
    -              #xmlText{value="\
    -    "},
    -              {kind,["custom"]},
    -              #xmlText{value="\
    -    "},
    -              {drive,["belt"]},
    -              #xmlText{value="\
    -  "}]},
    -       #xmlText{value="\
    -"}],
    +      [#xmlText{value="  "},
    +       {bike,[{year,"2003"},{color,"black"},{condition,"new"}],
    +             [#xmlText{value="\
    +    "},
    +              {name,[#xmlText{value="\
    +      "},
    +                     {manufacturer,["Harley Davidsson"]},
    +                     #xmlText{value="\
    +      "},
    +                     {brandName,["XL1200C"]},
    +                     #xmlText{value="\
    +      "},
    +                     {additionalName,["Sportster"]},
    +                     #xmlText{value="\
    +    "}]},
    +              {engine,["V-engine, 2-cylinders, 1200 cc"]},
    +              #xmlText{value="\
    +    "},
    +              {kind,["custom"]},
    +              #xmlText{value="\
    +    "},
    +              {drive,["belt"]},
    +              #xmlText{value="\
    +  "}]},
    +       #xmlText{value="\
    +"}],
         ...
    -    NewContent=Content++lists:flatten([Data]),
    -    NewRootEl=RootEl#xmlElement{content=NewContent},
    +    NewContent=Content++lists:flatten([Data]),
    +    NewRootEl=RootEl#xmlElement{content=NewContent},
         ...
    -    Prolog = ["<?xml version=\\"1.0\\" encoding=\\"utf-8\\" ?>
    +    Prolog = ["<?xml version=\\"1.0\\" encoding=\\"utf-8\\" ?>
     <!DOCTYPE motorcycles SYSTEM \\"motorcycles.dtd\\">\
    -"],
    -    Export=xmerl:export_simple([NewRootEl],xmerl_xml,[{prolog,Prolog}]),
    /usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_xs_examples.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (1283))
    --- old//usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_xs_examples.html	2026-08-21 04:00:32.897382471 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_xs_examples.html	2026-08-21 04:00:32.897382471 +0000
    @@ -93,13 +93,13 @@
         <h1>
           <xsl:apply-templates/>
         </h1>
    -</xsl:template>

    becomes in Erlang:

    template(E = #xmlElement{ parents=[{'doc',_}|_], name='title'}) ->
    -    ["<h1>",
    -         xslapply(fun template/1, E),
    -     "</h1>"];


    Example 2 Using value_of and select

    <xsl:template match="title">
    +</xsl:template>

    becomes in Erlang:

    template(E = #xmlElement{ parents=[{'doc',_}|_], name='title'}) ->
    +    ["<h1>",
    +         xslapply(fun template/1, E),
    +     "</h1>"];


    Example 2 Using value_of and select

    <xsl:template match="title">
       <div align="center"><h1><xsl:value-of select="." /></h1></div>
    -</xsl:template>

    becomes:

    template(E = #xmlElement{name='title'}) ->
    -    ["<div align=\"center\"><h1>", value_of(select(".", E)), "</h1></div>"];


    Example 3 Simple xsl stylesheet

    A complete example with the XSLT sheet in the xmerl distribution.

    <xsl:stylesheet version="1.0"
    +</xsl:template>

    becomes:

    template(E = #xmlElement{name='title'}) ->
    +    ["<div align=\"center\"><h1>", value_of(select(".", E)), "</h1></div>"];


    Example 3 Simple xsl stylesheet

    A complete example with the XSLT sheet in the xmerl distribution.

    <xsl:stylesheet version="1.0"
             xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
             xmlns="http://www.w3.org/TR/xhtml1/strict">
     
    @@ -160,60 +160,60 @@
         </em>
       </xsl:template>
     
    -</xsl:stylesheet>


    Example 4 Erlang version

    Erlang transformation of previous example:

    -include("xmerl.hrl").
    +</xsl:stylesheet>


    Example 4 Erlang version

    Erlang transformation of previous example:

    -include("xmerl.hrl").
     
    --import(xmerl_xs,
    -    [ xslapply/2, value_of/1, select/2, built_in_rules/2 ]).
    +-import(xmerl_xs,
    +    [ xslapply/2, value_of/1, select/2, built_in_rules/2 ]).
     
    -doctype()->
    +doctype()->
         "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\
      \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd \">".
     
    -process_xml(Doc)->
    -    template(Doc).
    +process_xml(Doc)->
    +    template(Doc).
     
    -template(E = #xmlElement{name='doc'})->
    -    [ "<\?xml version=\"1.0\" encoding=\"iso-8859-1\"\?>",
    -      doctype(),
    +template(E = #xmlElement{name='doc'})->
    +    [ "<\?xml version=\"1.0\" encoding=\"iso-8859-1\"\?>",
    +      doctype(),
           "<html xmlns=\"http://www.w3.org/1999/xhtml\" >"
           "<head>"
    -      "<title>", value_of(select("title",E)), "</title>"
    +      "<title>", value_of(select("title",E)), "</title>"
           "</head>"
           "<body>",
    -      xslapply( fun template/1, E),
    +      xslapply( fun template/1, E),
           "</body>"
    -      "</html>" ];
    +      "</html>" ];
     
     
    -template(E = #xmlElement{ parents=[{'doc',_}|_], name='title'}) ->
    -    ["<h1>",
    -     xslapply( fun template/1, E),
    -     "</h1>"];
    +template(E = #xmlElement{ parents=[{'doc',_}|_], name='title'}) ->
    +    ["<h1>",
    +     xslapply( fun template/1, E),
    +     "</h1>"];
     
    -template(E = #xmlElement{ parents=[{'chapter',_}|_], name='title'}) ->
    -    ["<h2>",
    -     xslapply( fun template/1, E),
    -     "</h2>"];
    +template(E = #xmlElement{ parents=[{'chapter',_}|_], name='title'}) ->
    +    ["<h2>",
    +     xslapply( fun template/1, E),
    +     "</h2>"];
     
    -template(E = #xmlElement{ parents=[{'section',_}|_], name='title'}) ->
    -    ["<h3>",
    -     xslapply( fun template/1, E),
    -     "</h3>"];
    +template(E = #xmlElement{ parents=[{'section',_}|_], name='title'}) ->
    +    ["<h3>",
    +     xslapply( fun template/1, E),
    +     "</h3>"];
     
    -template(E = #xmlElement{ name='para'}) ->
    -    ["<p>", xslapply( fun template/1, E), "</p>"];
    +template(E = #xmlElement{ name='para'}) ->
    +    ["<p>", xslapply( fun template/1, E), "</p>"];
     
    -template(E = #xmlElement{ name='note'}) ->
    -    ["<p class=\"note\">"
    +template(E = #xmlElement{ name='note'}) ->
    +    ["<p class=\"note\">"
          "<b>NOTE: </b>",
    -     xslapply( fun template/1, E),
    -     "</p>"];
    +     xslapply( fun template/1, E),
    +     "</p>"];
     
    -template(E = #xmlElement{ name='emph'}) ->
    -    ["<em>", xslapply( fun template/1, E), "</em>"];
    +template(E = #xmlElement{ name='emph'}) ->
    +    ["<em>", xslapply( fun template/1, E), "</em>"];
     
    -template(E)->
    -    built_in_rules( fun template/1, E).

    It is important to end with a call to xmerl_xs:built_in_rules/2 if you want any +template(E)-> + built_in_rules( fun template/1, E).

    It is important to end with a call to xmerl_xs:built_in_rules/2 if you want any text to be written in "push" transforms. That are the ones using a lot xslapply( fun template/1, E ) instead of value_of(select("xpath",E)), which is pull...


    The largest example is the stylesheet to transform this document from the Simplified Docbook XML format to xhtml. The source file is sdocbook2xhtml.erl.

    Tips and tricks

    for-each

    The function for-each is quite common in XSLT stylesheets. It can often be rewritten and replaced by select/1. Since select/1 returns a list of @@ -226,21 +226,21 @@ <xsl:template match="line"> <xsl:if test="position() mod 2 = 0">&#160;&#160;</xsl:if> <xsl:value-of select="." /><br /> -</xsl:template>

    Can be written as

    template(E = #xmlElement{name='stanza'}) ->
    -    {Lines,LineNo} = lists:mapfoldl(fun template_pos/2, 1, select("line", E)),
    -    ["<p>", Lines, "</p>"].
    +</xsl:template>

    Can be written as

    template(E = #xmlElement{name='stanza'}) ->
    +    {Lines,LineNo} = lists:mapfoldl(fun template_pos/2, 1, select("line", E)),
    +    ["<p>", Lines, "</p>"].
     
    -template_pos(E = #xmlElement{name='line'}, P) ->
    -    {[indent_line(P rem 2), value_of(E#xmlElement.content), "<br />"], P + 1 }.
    +template_pos(E = #xmlElement{name='line'}, P) ->
    +    {[indent_line(P rem 2), value_of(E#xmlElement.content), "<br />"], P + 1 }.
     
    -indent_line(0)->"&#160;&#160;";
    -indent_line(_)->"".

    Global tree awareness

    In XSLT you have "root" access to the top of the tree with XPath, even though +indent_line(0)->"&#160;&#160;"; +indent_line(_)->"".


    Global tree awareness

    In XSLT you have "root" access to the top of the tree with XPath, even though you are somewhere deep in your tree.

    The xslapply/2 function only carries back the child part of the tree to the template fun. But it is quite easy to write template funs that handles both the -child and top tree.


    Example 6 Passing the root tree

    The following example piece will prepend the article title to any section title

    template(E = #xmlElement{name='title'}, ETop ) ->
    -    ["<h3>", value_of(select("title", ETop))," - ",
    -     xslapply( fun(A) -> template(A, ETop) end, E),
    -     "</h3>"];

    +child and top tree.


    Example 6 Passing the root tree

    The following example piece will prepend the article title to any section title

    template(E = #xmlElement{name='title'}, ETop ) ->
    +    ["<h3>", value_of(select("title", ETop))," - ",
    +     xslapply( fun(A) -> template(A, ETop) end, E),
    +     "</h3>"];

    /usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_xsd.html differs (HTML document, Unicode text, UTF-8 text, with very long lines (737)) --- old//usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_xsd.html 2026-08-21 04:00:32.920382621 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/xmerl-2.1.9/doc/html/xmerl_xsd.html 2026-08-21 04:00:32.924382647 +0000 @@ -771,9 +771,9 @@ several times towards the same schema it reduces time consumption.

    The result, ValidElement, is the valid element that conforms to the post-schema-validation infoset. When the validator finds an error it tries to continue and reports a list of all errors found. In those cases an unexpected -error is found it may cause a single error reason.

    Usage example:

    1>{E,_} = xmerl_scan:file("my_XML_document.xml").
    -2>{ok,S} = xmerl_xsd:process_schema("my_XML_Schema.xsd").
    -3>{E2,_} = xmerl_xsd:validate(E,S).

    Observe that E2 may differ from E if for instance there are default values +error is found it may cause a single error reason.

    Usage example:

    1>{E,_} = xmerl_scan:file("my_XML_document.xml").
    +2>{ok,S} = xmerl_xsd:process_schema("my_XML_Schema.xsd").
    +3>{E2,_} = xmerl_xsd:validate(E,S).

    Observe that E2 may differ from E if for instance there are default values defined in my_XML_Schema.xsd.

    RPMS.2/erlang-jinterface-28.5.0.4-1.1.x86_64.rpm RPMS/erlang-jinterface-28.5.0.4-1.1.x86_64.rpm differ: byte 225, line 1 Comparing erlang-jinterface-28.5.0.4-1.1.x86_64.rpm to erlang-jinterface-28.5.0.4-1.1.x86_64.rpm comparing the rpm tags of erlang-jinterface --- old-rpm-tags +++ new-rpm-tags @@ -92 +92 @@ -/usr/lib64/erlang/lib/jinterface-1.15/priv/OtpErlang.jar 864209c7125d323779263092cc8c45149239a5ad9578932d5d07959977051c3c 0 +/usr/lib64/erlang/lib/jinterface-1.15/priv/OtpErlang.jar c5f8f19e2c3eaf2f69fe4b35334558700e5e5cd8d8a3173e34f3170f1d532a28 0 comparing rpmtags comparing RELEASE comparing PROVIDES comparing scripts comparing filelist comparing file checksum creating rename script RPM file checksum differs. Extracting packages Package content is identical overalldiffered=3 (number of pkgs that are not bit-by-bit identical: 0 is good) overall=1
  • {sctp_events, #sctp_event_subscribe{}}

    #sctp_event_subscribe{
    +Sockets API Extensions for SCTP.

  • {sctp_events, #sctp_event_subscribe{}}

    #sctp_event_subscribe{
             data_io_event          = true | false,
             association_event      = true | false,
             address_event          = true | false,
    @@ -176,42 +176,42 @@
             shutdown_event         = true | false,
             partial_delivery_event = true | false,
             adaptation_layer_event = true | false
    -}

    This option determines which SCTP Events that are to be +}

    This option determines which SCTP Events that are to be received (through recv/*) along with the data. The only exception is data_io_event, which enables or disables receiving of #sctp_sndrcvinfo{} ancillary data, not events. By default, all flags except adaptation_layer_event are enabled, although sctp_data_io_event and association_event are used by the driver -itself and not exported to the user level.

  • {sctp_delayed_ack_time, #sctp_assoc_value{}}

    #sctp_assoc_value{
    -      assoc_id    = assoc_id(),
    -      assoc_value = integer()
    -}

    Rarely used. Determines the ACK time (specified by assoc_value, in +itself and not exported to the user level.

  • {sctp_delayed_ack_time, #sctp_assoc_value{}}

    #sctp_assoc_value{
    +      assoc_id    = assoc_id(),
    +      assoc_value = integer()
    +}

    Rarely used. Determines the ACK time (specified by assoc_value, in milliseconds) for the specified association or the whole endpoint if -assoc_value = 0 (default).

  • {sctp_status, #sctp_status{}}

    #sctp_status{
    -      assoc_id            = assoc_id(),
    -      state               = atom(),
    -      rwnd                = integer(),
    -      unackdata           = integer(),
    -      penddata            = integer(),
    -      instrms             = integer(),
    -      outstrms            = integer(),
    -      fragmentation_point = integer(),
    -      primary             = #sctp_paddrinfo{}
    -}

    This option is read-only. It determines the status of the SCTP association +assoc_value = 0 (default).

  • {sctp_status, #sctp_status{}}

    #sctp_status{
    +      assoc_id            = assoc_id(),
    +      state               = atom(),
    +      rwnd                = integer(),
    +      unackdata           = integer(),
    +      penddata            = integer(),
    +      instrms             = integer(),
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/gen_tcp.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (898))
    --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/gen_tcp.xhtml	2026-08-05 05:56:49.000000000 +0000
    +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/gen_tcp.xhtml	2026-08-05 05:56:49.000000000 +0000
    @@ -24,27 +24,27 @@
           

    Interface to TCP/IP sockets.

    This module provides functions for communicating over TCP/IP protocol sockets.

    The following code fragment is a simple example of a client connecting to a -server at port 5678, transferring a binary, and closing the connection:

    client() ->
    +server at port 5678, transferring a binary, and closing the connection:

    client() ->
         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"),
    -    ok = gen_tcp:close(Sock).

    At the other end, a server is listening on port 5678, accepts the connection, -and receives the binary:

    server() ->
    -    {ok, LSock} = gen_tcp:listen(5678, [binary, {packet, 0},
    -                                        {active, false}]),
    -    {ok, Sock} = gen_tcp:accept(LSock),
    -    {ok, Bin} = do_recv(Sock, []),
    -    ok = gen_tcp:close(Sock),
    -    ok = gen_tcp:close(LSock),
    +    {ok, Sock} = gen_tcp:connect(SomeHostInNet, 5678,
    +                                 [binary, {packet, 0}]),
    +    ok = gen_tcp:send(Sock, "Some Data"),
    +    ok = gen_tcp:close(Sock).

    At the other end, a server is listening on port 5678, accepts the connection, +and receives the binary:

    server() ->
    +    {ok, LSock} = gen_tcp:listen(5678, [binary, {packet, 0},
    +                                        {active, false}]),
    +    {ok, Sock} = gen_tcp:accept(LSock),
    +    {ok, Bin} = do_recv(Sock, []),
    +    ok = gen_tcp:close(Sock),
    +    ok = gen_tcp:close(LSock),
         Bin.
     
    -do_recv(Sock, Bs) ->
    -    case gen_tcp:recv(Sock, 0) of
    -        {ok, B} ->
    -            do_recv(Sock, [Bs, B]);
    -        {error, closed} ->
    -            {ok, list_to_binary(Bs)}
    +do_recv(Sock, Bs) ->
    +    case gen_tcp:recv(Sock, 0) of
    +        {ok, B} ->
    +            do_recv(Sock, [Bs, B]);
    +        {error, closed} ->
    +            {ok, list_to_binary(Bs)}
         end.

    For more examples, see section Examples.

    Note

    Functions that create sockets can take an optional option; {inet_backend, Backend} that, if specified, has to be the first option. This selects the implementation backend towards the platform's socket API.

    This is a temporary option that will be ignored in a future release.

    The default is Backend = inet that selects the traditional inet_drv.c @@ -77,48 +77,48 @@ a single listening socket. Function start/2 takes the number of worker processes and the port number on which to listen for incoming connections. If LPort is specified as 0, an ephemeral port number is used, which is why the -start function returns the actual port number allocated:

    start(Num,LPort) ->
    -    case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of
    -        {ok, ListenSock} ->
    -            start_servers(Num,ListenSock),
    -            {ok, Port} = inet:port(ListenSock),
    +start function returns the actual port number allocated:

    start(Num,LPort) ->
    +    case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of
    +        {ok, ListenSock} ->
    +            start_servers(Num,ListenSock),
    +            {ok, Port} = inet:port(ListenSock),
                 Port;
    -        {error,Reason} ->
    -            {error,Reason}
    +        {error,Reason} ->
    +            {error,Reason}
         end.
     
    -start_servers(0,_) ->
    +start_servers(0,_) ->
         ok;
    -start_servers(Num,LS) ->
    -    spawn(?MODULE,server,[LS]),
    -    start_servers(Num-1,LS).
    +start_servers(Num,LS) ->
    +    spawn(?MODULE,server,[LS]),
    +    start_servers(Num-1,LS).
     
    -server(LS) ->
    -    case gen_tcp:accept(LS) of
    -        {ok,S} ->
    -            loop(S),
    -            server(LS);
    +server(LS) ->
    +    case gen_tcp:accept(LS) of
    +        {ok,S} ->
    +            loop(S),
    +            server(LS);
             Other ->
    -            io:format("accept returned ~w - goodbye!~n",[Other]),
    +            io:format("accept returned ~w - goodbye!~n",[Other]),
                 ok
         end.
     
    -loop(S) ->
    -    inet:setopts(S,[{active,once}]),
    +loop(S) ->
    +    inet:setopts(S,[{active,once}]),
         receive
    -        {tcp,S,Data} ->
    -            Answer = process(Data), % Not implemented in this example
    -            gen_tcp:send(S,Answer),
    -            loop(S);
    -        {tcp_closed,S} ->
    -            io:format("Socket ~w closed [~w]~n",[S,self()]),
    +        {tcp,S,Data} ->
    +            Answer = process(Data), % Not implemented in this example
    +            gen_tcp:send(S,Answer),
    +            loop(S);
    +        {tcp_closed,S} ->
    +            io:format("Socket ~w closed [~w]~n",[S,self()]),
                 ok
    -    end.

    Example of a simple client:

    client(PortNo,Message) ->
    -    {ok,Sock} = gen_tcp:connect("localhost",PortNo,[{active,false},
    -                                                    {packet,2}]),
    -    gen_tcp:send(Sock,Message),
    -    A = gen_tcp:recv(Sock,0),
    -    gen_tcp:close(Sock),
    +    end.

    Example of a simple client:

    client(PortNo,Message) ->
    +    {ok,Sock} = gen_tcp:connect("localhost",PortNo,[{active,false},
    +                                                    {packet,2}]),
    +    gen_tcp:send(Sock,Message),
    +    A = gen_tcp:recv(Sock,0),
    +    gen_tcp:close(Sock),
         A.

    The send call does not accept a time-out option because time-outs on send is handled through socket option send_timeout. The behavior of a send operation with no receiver is mainly defined by the underlying TCP stack and the network @@ -128,32 +128,32 @@ does not get any acknowledge for each message it sends, but has to rely on the send time-out option to detect that the other end is unresponsive. Option send_timeout can be used when connecting:

    ...
    -{ok,Sock} = gen_tcp:connect(HostAddress, Port,
    -                            [{active,false},
    -                             {send_timeout, 5000},
    -                             {packet,2}]),
    -                loop(Sock), % See below
    -...

    In the loop where requests are handled, send time-outs can now be detected:

    loop(Sock) ->
    +{ok,Sock} = gen_tcp:connect(HostAddress, Port,
    +                            [{active,false},
    +                             {send_timeout, 5000},
    +                             {packet,2}]),
    +                loop(Sock), % See below
    +...

    In the loop where requests are handled, send time-outs can now be detected:

    loop(Sock) ->
         receive
    -        {Client, send_data, Binary} ->
    -            case gen_tcp:send(Sock,[Binary]) of
    -                {error, timeout} ->
    -                    io:format("Send timeout, closing!~n",
    -                              []),
    -                    handle_send_timeout(), % Not implemented here
    -                    Client ! {self(),{error_sending, timeout}},
    +        {Client, send_data, Binary} ->
    +            case gen_tcp:send(Sock,[Binary]) of
    +                {error, timeout} ->
    +                    io:format("Send timeout, closing!~n",
    +                              []),
    +                    handle_send_timeout(), % Not implemented here
    +                    Client ! {self(),{error_sending, timeout}},
                         %% Usually, it's a good idea to give up in case of a
                         %% send timeout, as you never know how much actually
                         %% reached the server, maybe only a packet header?!
    -                    gen_tcp:close(Sock);
    -                {error, OtherSendError} ->
    -                    io:format("Some other error on socket (~p), closing",
    -                              [OtherSendError]),
    -                    Client ! {self(),{error_sending, OtherSendError}},
    -                    gen_tcp:close(Sock);
    +                    gen_tcp:close(Sock);
    +                {error, OtherSendError} ->
    +                    io:format("Some other error on socket (~p), closing",
    +                              [OtherSendError]),
    +                    Client ! {self(),{error_sending, OtherSendError}},
    +                    gen_tcp:close(Sock);
                     ok ->
    -                    Client ! {self(), data_sent},
    -                    loop(Sock)
    +                    Client ! {self(), data_sent},
    +                    loop(Sock)
                 end
         end.

    Usually it suffices to detect time-outs on receive, as most protocols include some sort of acknowledgment from the server, but if the protocol is strictly one /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/gen_udp.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (770)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/gen_udp.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/gen_udp.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -832,8 +832,8 @@ Leaves a multicast group.

  • option/0 - See inet:setopts/2.

  • UDP packets are sent with this socket using send(Socket, ...). When UDP packets arrive to the Socket's UDP port, and the socket is in an active mode, the packets are delivered as messages to the -controlling process (socket owner):

    {udp, Socket, PeerIP, PeerPort, Packet} % Without ancillary data
    -{udp, Socket, PeerIP, PeerPort, AncData, Packet} % With ancillary data

    PeerIP and PeerPort are the address from which Packet was sent. +controlling process (socket owner):

    {udp, Socket, PeerIP, PeerPort, Packet} % Without ancillary data
    +{udp, Socket, PeerIP, PeerPort, AncData, Packet} % With ancillary data

    PeerIP and PeerPort are the address from which Packet was sent. Packet is a list of bytes ([byte/0] if option list is active and a binary/0 if option binaryis active (they are mutually exclusive).

    The message contains an AncData field only if any of the socket @@ -841,8 +841,8 @@ recvtclass or recvttl are active.

    When a socket in {active, N} mode (see inet:setopts/2 for details), transitions to passive ({active, false}) mode (N counts down to 0), -the controlling process is notified by a message on this form:

    {udp_passive, Socket}

    If the OS protocol stack reports an error for the socket, the following -message is sent to the controlling process:

    {udp_error, Socket, Reason}

    Reason is mostly a POSIX Error Code.

    If the socket is in passive mode (not in an active mode), received data +the controlling process is notified by a message on this form:

    {udp_passive, Socket}

    If the OS protocol stack reports an error for the socket, the following +message is sent to the controlling process:

    {udp_error, Socket, Reason}

    Reason is mostly a POSIX Error Code.

    If the socket is in passive mode (not in an active mode), received data can be retrieved with therecv/2,3](recv/2) calls. Note that incoming UDP packets that are longer than the receive buffer option specifies can be truncated without warning.

    The default value for the receive buffer option is {recbuf, 9216}.

    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/global_group.xhtml differs (HTML document, ASCII text, with very long lines (727)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/global_group.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/global_group.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -26,7 +26,7 @@ groups. Each global group has its own global namespace, see global.

    The main advantage of dividing systems into global groups is that the background load decreases while the number of nodes to be updated is reduced when manipulating globally registered names.

    The Kernel configuration parameter global_groups -defines the global groups:

    {global_groups, [GroupTuple :: group_tuple()]}

    For the processes and nodes to run smoothly using the global group +defines the global groups:

    {global_groups, [GroupTuple :: group_tuple()]}

    For the processes and nodes to run smoothly using the global group functionality, the following criteria must be met:

    • An instance of the global group server, global_group, must be running on each node. The processes are automatically started and synchronized when a node is started.
    • All involved nodes must agree on the global group definition, otherwise the /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/inet_res.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (1007)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/inet_res.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/inet_res.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -67,15 +67,15 @@ the legacy behaviour to reuse the UDP socket on retries and use sequential transaction ID:s can be configured by setting the resolver option random to false.

      Resolver Types

      The following data types concern the resolver:

      DNS Types

      The following data types concern the DNS client:

      Example

      This access functions example shows how lookup/3 can be implemented using -resolve/3 from outside the module:

      example_lookup(Name, Class, Type) ->
      -    case inet_res:resolve(Name, Class, Type) of
      -        {ok,Msg} ->
      -            [inet_dns:rr(RR, data)
      -             || RR <- inet_dns:msg(Msg, anlist),
      -                 inet_dns:rr(RR, type) =:= Type,
      -                 inet_dns:rr(RR, class) =:= Class];
      -        {error,_} ->
      -            []
      +resolve/3 from outside the module:

      example_lookup(Name, Class, Type) ->
      +    case inet_res:resolve(Name, Class, Type) of
      +        {ok,Msg} ->
      +            [inet_dns:rr(RR, data)
      +             || RR <- inet_dns:msg(Msg, anlist),
      +                 inet_dns:rr(RR, type) =:= Type,
      +                 inet_dns:rr(RR, class) =:= Class];
      +        {error,_} ->
      +            []
            end.
      @@ -501,57 +501,57 @@

      A DNS message.

      This is the start of a hierarchy of opaque data structures that can be examined with access functions in inet_dns, which return lists of {Field,Value} tuples. The arity 2 functions return the value -for a specified field.

      dns_msg() = DnsMsg
      -    inet_dns:msg(DnsMsg) ->
      -        [ {header, dns_header()}
      -        | {qdlist, dns_query()}
      -        | {anlist, dns_rr()}
      -        | {nslist, dns_rr()}
      -        | {arlist, dns_rr()} ]
      -    inet_dns:msg(DnsMsg, header) -> dns_header() % for example
      -    inet_dns:msg(DnsMsg, Field) -> Value
      -
      -dns_header() = DnsHeader
      -    inet_dns:header(DnsHeader) ->
      -        [ {id, integer()}
      -        | {qr, boolean()}
      -        | {opcode, query | iquery | status | integer()}
      -        | {aa, boolean()}
      -        | {tc, boolean()}
      -        | {rd, boolean()}
      -        | {ra, boolean()}
      -        | {pr, boolean()}
      -        | {rcode, integer(0..16)} ]
      -    inet_dns:header(DnsHeader, Field) -> Value
      -
      -query_type() = axfr | mailb | maila | any | dns_rr_type()
      -
      -dns_query() = DnsQuery
      -    inet_dns:dns_query(DnsQuery) ->
      -        [ {domain, dns_name()}
      -        | {type, query_type()}
      -        | {class, dns_class()} ]
      -    inet_dns:dns_query(DnsQuery, Field) -> Value
      -
      -dns_rr() = DnsRr
      -    inet_dns:rr(DnsRr) -> DnsRrFields | DnsRrOptFields
      -    DnsRrFields = [ {domain, dns_name()}
      -                  | {type, dns_rr_type()}
      -                  | {class, dns_class()}
      -                  | {ttl, integer()}
      -                  | {data, dns_data()} ]
      -    DnsRrOptFields = [ {domain, dns_name()}
      -                     | {type, opt}
      -                     | {udp_payload_size, integer()}
      -                     | {ext_rcode, integer()}
      -                     | {version, integer()}
      -                     | {z, integer()}
      -                     | {data, dns_data()} ]
      -    inet_dns:rr(DnsRr, Field) -> Value

      There is an information function for the types above:

      inet_dns:record_type(dns_msg()) -> msg;
      -inet_dns:record_type(dns_header()) -> header;
      -inet_dns:record_type(dns_query()) -> dns_query;
      -inet_dns:record_type(dns_rr()) -> rr;
      -inet_dns:record_type(_) -> undefined.

      So, inet_dns:(inet_dns:record_type(X))(X) converts any of these data +for a specified field.

      dns_msg() = DnsMsg
      +    inet_dns:msg(DnsMsg) ->
      +        [ {header, dns_header()}
      +        | {qdlist, dns_query()}
      +        | {anlist, dns_rr()}
      +        | {nslist, dns_rr()}
      +        | {arlist, dns_rr()} ]
      +    inet_dns:msg(DnsMsg, header) -> dns_header() % for example
      +    inet_dns:msg(DnsMsg, Field) -> Value
      +
      +dns_header() = DnsHeader
      +    inet_dns:header(DnsHeader) ->
      +        [ {id, integer()}
      +        | {qr, boolean()}
      +        | {opcode, query | iquery | status | integer()}
      +        | {aa, boolean()}
      +        | {tc, boolean()}
      +        | {rd, boolean()}
      +        | {ra, boolean()}
      +        | {pr, boolean()}
      +        | {rcode, integer(0..16)} ]
      +    inet_dns:header(DnsHeader, Field) -> Value
      +
      +query_type() = axfr | mailb | maila | any | dns_rr_type()
      +
      +dns_query() = DnsQuery
      +    inet_dns:dns_query(DnsQuery) ->
      +        [ {domain, dns_name()}
      +        | {type, query_type()}
      +        | {class, dns_class()} ]
      +    inet_dns:dns_query(DnsQuery, Field) -> Value
      +
      +dns_rr() = DnsRr
      +    inet_dns:rr(DnsRr) -> DnsRrFields | DnsRrOptFields
      +    DnsRrFields = [ {domain, dns_name()}
      +                  | {type, dns_rr_type()}
      +                  | {class, dns_class()}
      +                  | {ttl, integer()}
      +                  | {data, dns_data()} ]
      +    DnsRrOptFields = [ {domain, dns_name()}
      +                     | {type, opt}
      +                     | {udp_payload_size, integer()}
      +                     | {ext_rcode, integer()}
      +                     | {version, integer()}
      +                     | {z, integer()}
      +                     | {data, dns_data()} ]
      +    inet_dns:rr(DnsRr, Field) -> Value

      There is an information function for the types above:

      inet_dns:record_type(dns_msg()) -> msg;
      +inet_dns:record_type(dns_header()) -> header;
      +inet_dns:record_type(dns_query()) -> dns_query;
      +inet_dns:record_type(dns_rr()) -> rr;
      +inet_dns:record_type(_) -> undefined.

      So, inet_dns:(inet_dns:record_type(X))(X) converts any of these data structures into a {Field,Value} list.

      /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/inet.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (10374)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/inet.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/inet.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -49,19 +49,19 @@ or as a tuple {150, 236, 20, 73}.

      IPv4 address examples:

      Address          ip_address()
       -------          ------------
       127.0.0.1        {127,0,0,1}
      -192.168.42.2     {192,168,42,2}

      IPv6 address examples:

      Address          ip_address()
      +192.168.42.2     {192,168,42,2}

      IPv6 address examples:

      Address          ip_address()
       -------          ------------
      -::1             {0,0,0,0,0,0,0,1}
      -::192.168.42.2  {0,0,0,0,0,0,(192 bsl 8) bor 168,(42 bsl 8) bor 2}
      +::1             {0,0,0,0,0,0,0,1}
      +::192.168.42.2  {0,0,0,0,0,0,(192 bsl 8) bor 168,(42 bsl 8) bor 2}
       ::FFFF:192.168.42.2
      -                {0,0,0,0,0,16#FFFF,(192 bsl 8) bor 168,(42 bsl 8) bor 2}
      +                {0,0,0,0,0,16#FFFF,(192 bsl 8) bor 168,(42 bsl 8) bor 2}
       3ffe:b80:1f8d:2:204:acff:fe17:bf38
      -                {16#3ffe,16#b80,16#1f8d,16#2,16#204,16#acff,16#fe17,16#bf38}
      +                {16#3ffe,16#b80,16#1f8d,16#2,16#204,16#acff,16#fe17,16#bf38}
       fe80::204:acff:fe17:bf38
      -                {16#fe80,0,0,0,16#204,16#acff,16#fe17,16#bf38}

      Function parse_address/1 can be useful:

      1> inet:parse_address("192.168.42.2").
      -{ok,{192,168,42,2}}
      -2> inet:parse_address("::FFFF:192.168.42.2").
      -{ok,{0,0,0,0,0,65535,49320,10754}}

      POSIX Error Codes

      • e2big - Too long argument list
      • eacces - Permission denied
      • eaddrinuse - Address already in use
      • eaddrnotavail - Cannot assign requested address
      • eadv - Advertise error
      • eafnosupport - Address family not supported by protocol family
      • eagain - Resource temporarily unavailable
      • ealign - EALIGN
      • ealready - Operation already in progress
      • ebade - Bad exchange descriptor
      • ebadf - Bad file number
      • ebadfd - File descriptor in bad state
      • ebadmsg - Not a data message
      • ebadr - Bad request descriptor
      • ebadrpc - Bad RPC structure
      • ebadrqc - Bad request code
      • ebadslt - Invalid slot
      • ebfont - Bad font file format
      • ebusy - File busy
      • echild - No children
      • echrng - Channel number out of range
      • ecomm - Communication error on send
      • econnaborted - Software caused connection abort
      • econnrefused - Connection refused
      • econnreset - Connection reset by peer
      • edeadlk - Resource deadlock avoided
      • edeadlock - Resource deadlock avoided
      • edestaddrreq - Destination address required
      • edirty - Mounting a dirty fs without force
      • edom - Math argument out of range
      • edotdot - Cross mount point
      • edquot - Disk quota exceeded
      • eduppkg - Duplicate package name
      • eexist - File already exists
      • efault - Bad address in system call argument
      • efbig - File too large
      • ehostdown - Host is down
      • ehostunreach - Host is unreachable
      • eidrm - Identifier removed
      • einit - Initialization error
      • einprogress - Operation now in progress
      • eintr - Interrupted system call
      • einval - Invalid argument
      • eio - I/O error
      • eisconn - Socket is already connected
      • eisdir - Illegal operation on a directory
      • eisnam - Is a named file
      • el2hlt - Level 2 halted
      • el2nsync - Level 2 not synchronized
      • el3hlt - Level 3 halted
      • el3rst - Level 3 reset
      • elbin - ELBIN
      • elibacc - Cannot access a needed shared library
      • elibbad - Accessing a corrupted shared library
      • elibexec - Cannot exec a shared library directly
      • elibmax - Attempting to link in more shared libraries than system limit
      • elibscn - .lib section in a.out corrupted
      • elnrng - Link number out of range
      • eloop - Too many levels of symbolic links
      • emfile - Too many open files
      • emlink - Too many links
      • emsgsize - Message too long
      • emultihop - Multihop attempted
      • enametoolong - Filename too long
      • enavail - Unavailable
      • enet - ENET
      • enetdown - Network is down
      • enetreset - Network dropped connection on reset
      • enetunreach - Network is unreachable
      • enfile - File table overflow
      • enoano - Anode table overflow
      • enobufs - No buffer space available
      • enocsi - No CSI structure available
      • enodata - No data available
      • enodev - No such device
      • enoent - No such file or directory
      • enoexec - Exec format error
      • enolck - No locks available
      • enolink - Link has been severed
      • enomem - Not enough memory
      • enomsg - No message of desired type
      • enonet - Machine is not on the network
      • enopkg - Package not installed
      • enoprotoopt - Bad protocol option
      • enospc - No space left on device
      • enosr - Out of stream resources or not a stream device
      • enosym - Unresolved symbol name
      • enosys - Function not implemented
      • enotblk - Block device required
      • enotconn - Socket is not connected
      • enotdir - Not a directory
      • enotempty - Directory not empty
      • enotnam - Not a named file
      • enotsock - Socket operation on non-socket
      • enotsup - Operation not supported
      • enotty - Inappropriate device for ioctl
      • enotuniq - Name not unique on network
      • enxio - No such device or address
      • eopnotsupp - Operation not supported on socket
      • eperm - Not owner
      • epfnosupport - Protocol family not supported
      • epipe - Broken pipe
      • eproclim - Too many processes
      • eprocunavail - Bad procedure for program
      • eprogmismatch - Wrong program version
      • eprogunavail - RPC program unavailable
      • eproto - Protocol error
      • eprotonosupport - Protocol not supported
      • eprototype - Wrong protocol type for socket
      • erange - Math result unrepresentable
      • erefused - EREFUSED
      • eremchg - Remote address changed
      • eremdev - Remote device
      • eremote - Pathname hit remote filesystem
      • eremoteio - Remote I/O error
      • eremoterelease - EREMOTERELEASE
      • erofs - Read-only filesystem
      • erpcmismatch - Wrong RPC version
      • erremote - Object is remote
      • eshutdown - Cannot send after socket shutdown
      • esocktnosupport - Socket type not supported
      • espipe - Invalid seek
      • esrch - No such process
      • esrmnt - Srmount error
      • estale - Stale remote file handle
      • esuccess - Error 0
      • etime - Timer expired
      • etimedout - Connection timed out
      • etoomanyrefs - Too many references
      • etxtbsy - Text file or pseudo-device busy
      • euclean - Structure needs cleaning
      • eunatch - Protocol driver not attached
      • eusers - Too many users
      • eversion - Version mismatch
      • ewouldblock - Operation would block
      • exdev - Cross-device link
      • exfull - Message tables full
      • nxdomain - Hostname or domain name cannot be found
      +
      {16#fe80,0,0,0,16#204,16#acff,16#fe17,16#bf38}

      Function parse_address/1 can be useful:

      1> inet:parse_address("192.168.42.2").
      +{ok,{192,168,42,2}}
      +2> inet:parse_address("::FFFF:192.168.42.2").
      +{ok,{0,0,0,0,0,65535,49320,10754}}

      POSIX Error Codes

      • e2big - Too long argument list
      • eacces - Permission denied
      • eaddrinuse - Address already in use
      • eaddrnotavail - Cannot assign requested address
      • eadv - Advertise error
      • eafnosupport - Address family not supported by protocol family
      • eagain - Resource temporarily unavailable
      • ealign - EALIGN
      • ealready - Operation already in progress
      • ebade - Bad exchange descriptor
      • ebadf - Bad file number
      • ebadfd - File descriptor in bad state
      • ebadmsg - Not a data message
      • ebadr - Bad request descriptor
      • ebadrpc - Bad RPC structure
      • ebadrqc - Bad request code
      • ebadslt - Invalid slot
      • ebfont - Bad font file format
      • ebusy - File busy
      • echild - No children
      • echrng - Channel number out of range
      • ecomm - Communication error on send
      • econnaborted - Software caused connection abort
      • econnrefused - Connection refused
      • econnreset - Connection reset by peer
      • edeadlk - Resource deadlock avoided
      • edeadlock - Resource deadlock avoided
      • edestaddrreq - Destination address required
      • edirty - Mounting a dirty fs without force
      • edom - Math argument out of range
      • edotdot - Cross mount point
      • edquot - Disk quota exceeded
      • eduppkg - Duplicate package name
      • eexist - File already exists
      • efault - Bad address in system call argument
      • efbig - File too large
      • ehostdown - Host is down
      • ehostunreach - Host is unreachable
      • eidrm - Identifier removed
      • einit - Initialization error
      • einprogress - Operation now in progress
      • eintr - Interrupted system call
      • einval - Invalid argument
      • eio - I/O error
      • eisconn - Socket is already connected
      • eisdir - Illegal operation on a directory
      • eisnam - Is a named file
      • el2hlt - Level 2 halted
      • el2nsync - Level 2 not synchronized
      • el3hlt - Level 3 halted
      • el3rst - Level 3 reset
      • elbin - ELBIN
      • elibacc - Cannot access a needed shared library
      • elibbad - Accessing a corrupted shared library
      • elibexec - Cannot exec a shared library directly
      • elibmax - Attempting to link in more shared libraries than system limit
      • elibscn - .lib section in a.out corrupted
      • elnrng - Link number out of range
      • eloop - Too many levels of symbolic links
      • emfile - Too many open files
      • emlink - Too many links
      • emsgsize - Message too long
      • emultihop - Multihop attempted
      • enametoolong - Filename too long
      • enavail - Unavailable
      • enet - ENET
      • enetdown - Network is down
      • enetreset - Network dropped connection on reset
      • enetunreach - Network is unreachable
      • enfile - File table overflow
      • enoano - Anode table overflow
      • enobufs - No buffer space available
      • enocsi - No CSI structure available
      • enodata - No data available
      • enodev - No such device
      • enoent - No such file or directory
      • enoexec - Exec format error
      • enolck - No locks available
      • enolink - Link has been severed
      • enomem - Not enough memory
      • enomsg - No message of desired type
      • enonet - Machine is not on the network
      • enopkg - Package not installed
      • enoprotoopt - Bad protocol option
      • enospc - No space left on device
      • enosr - Out of stream resources or not a stream device
      • enosym - Unresolved symbol name
      • enosys - Function not implemented
      • enotblk - Block device required
      • enotconn - Socket is not connected
      • enotdir - Not a directory
      • enotempty - Directory not empty
      • enotnam - Not a named file
      • enotsock - Socket operation on non-socket
      • enotsup - Operation not supported
      • enotty - Inappropriate device for ioctl
      • enotuniq - Name not unique on network
      • enxio - No such device or address
      • eopnotsupp - Operation not supported on socket
      • eperm - Not owner
      • epfnosupport - Protocol family not supported
      • epipe - Broken pipe
      • eproclim - Too many processes
      • eprocunavail - Bad procedure for program
      • eprogmismatch - Wrong program version
      • eprogunavail - RPC program unavailable
      • eproto - Protocol error
      • eprotonosupport - Protocol not supported
      • eprototype - Wrong protocol type for socket
      • erange - Math result unrepresentable
      • erefused - EREFUSED
      • eremchg - Remote address changed
      • eremdev - Remote device
      • eremote - Pathname hit remote filesystem
      • eremoteio - Remote I/O error
      • eremoterelease - EREMOTERELEASE
      • erofs - Read-only filesystem
      • erpcmismatch - Wrong RPC version
      • erremote - Object is remote
      • eshutdown - Cannot send after socket shutdown
      • esocktnosupport - Socket type not supported
      • espipe - Invalid seek
      • esrch - No such process
      • esrmnt - Srmount error
      • estale - Stale remote file handle
      • esuccess - Error 0
      • etime - Timer expired
      • etimedout - Connection timed out
      • etoomanyrefs - Too many references
      • etxtbsy - Text file or pseudo-device busy
      • euclean - Structure needs cleaning
      • eunatch - Protocol driver not attached
      • eusers - Too many users
      • eversion - Version mismatch
      • ewouldblock - Operation would block
      • exdev - Cross-device link
      • exfull - Message tables full
      • nxdomain - Hostname or domain name cannot be found
      @@ -846,7 +846,7 @@

      A record describing a host; name and address.

      Corresponds to the C: struct hostent as returned by for example -gethostbyname(3).

      The record is defined in the Kernel include file "inet.hrl".

      Add the following directive to the module:

      -include_lib("kernel/include/inet.hrl").
      +gethostbyname(3).

      The record is defined in the Kernel include file "inet.hrl".

      Add the following directive to the module:

      -include_lib("kernel/include/inet.hrl").
      @@ -1998,9 +1998,9 @@ this information, you need to know the following:

      • The numeric value of protocol level IPPROTO_TCP
      • The numeric value of option TCP_INFO
      • The size of struct tcp_info
      • The size and offset of the specific field

      By inspecting the headers or writing a small C program, it is found that IPPROTO_TCP is 6, TCP_INFO is 11, the structure size is 92 (bytes), the offset of tcpi_sacked is 28 bytes, and the value is a 32-bit integer. The -following code can be used to retrieve the value:

      get_tcpi_sacked(Sock) ->
      -    {ok,[{raw,_,_,Info}]} = inet:getopts(Sock,[{raw,6,11,92}]),
      -    <<_:28/binary,TcpiSacked:32/native,_/binary>> = Info,
      +following code can be used to retrieve the value:

      get_tcpi_sacked(Sock) ->
      +    {ok,[{raw,_,_,Info}]} = inet:getopts(Sock,[{raw,6,11,92}]),
      +    <<_:28/binary,TcpiSacked:32/native,_/binary>> = Info,
           TcpiSacked.

      Preferably, you would check the machine type, the operating system, and the Kernel version before executing anything similar to this code.

      @@ -2351,7 +2351,7 @@

      Start a socket monitor.

      If the Socket to monitor doesn't exist or when the monitor is triggered, -a 'DOWN' message is sent that has the following pattern:

      	    {'DOWN', MonitorRef, Type, Object, Info}
      • MonitorRef - The return value from this function.

      • Type - The type of socket, can be one of the following +a 'DOWN' message is sent that has the following pattern:

        	    {'DOWN', MonitorRef, Type, Object, Info}
        • MonitorRef - The return value from this function.

        • Type - The type of socket, can be one of the following atom/0s: port or socket.

        • Object - The monitored entity, the socket, which triggered the event.

        • Info - Either the termination reason of the socket or nosock (the Socket did not exist when this function was called).

        Making several calls to inet:monitor/1 for the same Socket is not an error; one monitor is created per call.

        The monitor is triggered when the socket is closed in any way such as /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_chapter.xhtml differs (HTML document, ASCII text, with very long lines (1531)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_chapter.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -70,7 +70,7 @@ up to the handler implementation if other processes are involved or not.

        The handlers are called in sequence, and the order is not defined.

        Logger API

        The API for logging consists of a set of macros, and a set of functions of the form logger:Level/1,2,3, which are all shortcuts for logger:log(Level,Arg1[,Arg2[,Arg3]]).

        The macros are defined in logger.hrl, which is included in a module with the -directive

        -include_lib("kernel/include/logger.hrl").

        The difference between using the macros and the exported functions is that +directive

        -include_lib("kernel/include/logger.hrl").

        The difference between using the macros and the exported functions is that macros add location (originator) information to the metadata, and performs lazy evaluation by wrapping the logger call in a case statement, so it is only evaluated if the log level of the event passes the primary log level check.

        Log Level

        The log level indicates the severity of a event. In accordance with the Syslog @@ -80,23 +80,23 @@ must always use the atom. To compare the severity of two log levels, use logger:compare_levels/2.

        Log Message

        The log message contains the information to be logged. The message can consist of a format string and arguments (given as two separate parameters in the Logger -API), a string or a report.

        Example, format string and arguments:

        logger:error("The file does not exist: ~ts",[Filename])

        Example, string:

        logger:notice("Something strange happened!")

        A report, which is either a map or a key-value list, is the preferred way to log +API), a string or a report.

        Example, format string and arguments:

        logger:error("The file does not exist: ~ts",[Filename])

        Example, string:

        logger:notice("Something strange happened!")

        A report, which is either a map or a key-value list, is the preferred way to log using Logger as it makes it possible for different backends to filter and format -the log event as it needs to.

        Example, report:

        ?LOG_ERROR(#{ user => joe, filename => Filename, reason => enoent })

        Reports can be accompanied by a report callback specified in the log event's +the log event as it needs to.

        Example, report:

        ?LOG_ERROR(#{ user => joe, filename => Filename, reason => enoent })

        Reports can be accompanied by a report callback specified in the log event's metadata. The report callback is a convenience function that the formatter can use to convert the report to a format string and arguments, or directly to a string. The formatter can also use its own conversion function, if no callback is provided, or if a customized formatting is desired.

        The report callback must be a fun with one or two arguments. If it takes one argument, this is the report itself, and the fun returns a format string and -arguments:

        fun((logger:report()) -> {io:format(),[term()]})

        If it takes two arguments, the first is the report, and the second is a map -containing extra data that allows direct conversion to a string:

        fun((logger:report(),logger:report_cb_config()) -> unicode:chardata())

        The fun must obey the depth and chars_limit parameters provided in the +arguments:

        fun((logger:report()) -> {io:format(),[term()]})

        If it takes two arguments, the first is the report, and the second is a map +containing extra data that allows direct conversion to a string:

        fun((logger:report(),logger:report_cb_config()) -> unicode:chardata())

        The fun must obey the depth and chars_limit parameters provided in the second argument, as the formatter cannot do anything useful of these parameters with the returned string. The extra data also contains a field named single_line, indicating if the printed log message may contain line breaks or not. This variant is used when the formatting of the report depends on the size -or single line parameters.

        Example, report, and metadata with report callback:

        logger:debug(#{got => connection_request, id => Id, state => State},
        -             #{report_cb => fun(R) -> {"~p",[R]} end})

        The log message can also be provided through a fun for lazy evaluation. The fun +or single line parameters.

        Example, report, and metadata with report callback:

        logger:debug(#{got => connection_request, id => Id, state => State},
        +             #{report_cb => fun(R) -> {"~p",[R]} end})

        The log message can also be provided through a fun for lazy evaluation. The fun is only evaluated if the primary log level check passes, and is therefore recommended if it is expensive to generate the message. The lazy fun must return a string, a report, or a tuple with format string and arguments.

        Metadata

        Metadata contains additional data associated with a log message. Logger inserts @@ -235,12 +235,12 @@ proxy configuration.

        Config is any (zero or more) of the following:

        • {handler, default, undefined} - Disables the default handler. This allows another application to add its own default handler.

          Only one entry of this type is allowed.

        • {handler, HandlerId, Module, HandlerConfig} - If HandlerId is default, then this entry modifies the default handler, equivalent to -calling

          logger:remove_handler(default)

          followed by

          logger:add_handler(default, Module, HandlerConfig)

          For all other values of HandlerId, this entry adds a new handler, -equivalent to calling

          logger:add_handler(HandlerId, Module, HandlerConfig)

          Multiple entries of this type are allowed.

        • {filters, FilterDefault, [Filter]} - Adds the specified primary -filters.

          • FilterDefault = log | stop

          • Filter = {FilterId, {FilterFun, FilterConfig}}

          Equivalent to calling

          logger:add_primary_filter(FilterId, {FilterFun, FilterConfig})

          for each Filter.

          FilterDefault specifies the behaviour if all primary filters return +calling

          logger:remove_handler(default)

          followed by

          logger:add_handler(default, Module, HandlerConfig)

          For all other values of HandlerId, this entry adds a new handler, +equivalent to calling

          logger:add_handler(HandlerId, Module, HandlerConfig)

          Multiple entries of this type are allowed.

        • {filters, FilterDefault, [Filter]} - Adds the specified primary +filters.

          • FilterDefault = log | stop

          • Filter = {FilterId, {FilterFun, FilterConfig}}

          Equivalent to calling

          logger:add_primary_filter(FilterId, {FilterFun, FilterConfig})

          for each Filter.

          FilterDefault specifies the behaviour if all primary filters return ignore, see section Filters.

          Only one entry of this type is allowed.

        • {module_level, Level, [Module]} - Sets module log level for the given -modules. Equivalent to calling

          logger:set_module_level(Module, Level)

          for each Module.

          Multiple entries of this type are allowed.

        • {proxy, ProxyConfig} - Sets the proxy configuration, equivalent to -calling

          logger:set_proxy_config(ProxyConfig)

          Only one entry of this type is allowed.

        See section Configuration Examples for +modules. Equivalent to calling

        logger:set_module_level(Module, Level)

        for each Module.

        Multiple entries of this type are allowed.

      • {proxy, ProxyConfig} - Sets the proxy configuration, equivalent to +calling

        logger:set_proxy_config(ProxyConfig)

        Only one entry of this type is allowed.

      See section Configuration Examples for examples using the logger parameter for system configuration.

    • logger_metadata = map() - Specifies the primary metadata. See the kernel(6) manual page for more information about this parameter.

    • logger_level = Level - Specifies the primary log @@ -255,31 +255,31 @@ file. See the config(4) manual page for more information about this file.

      Each of the following examples shows a simple system configuration file that configures Logger according to the description.

      Modify the default handler to print to a file instead of -standard_io:

      [{kernel,
      -  [{logger,
      -    [{handler, default, logger_std_h,  % {handler, HandlerId, Module,
      -      #{config => #{file => "log/erlang.log"}}}  % Config}
      -    ]}]}].

      Modify the default handler to print each log event as a single line:

      [{kernel,
      -  [{logger,
      -    [{handler, default, logger_std_h,
      -      #{formatter => {logger_formatter, #{single_line => true}}}}
      -    ]}]}].

      Modify the default handler to print the pid of the logging process for each log -event:

      [{kernel,
      -  [{logger,
      -    [{handler, default, logger_std_h,
      -      #{formatter => {logger_formatter,
      -                        #{template => [time," ",pid," ",msg,"\n"]}}}}
      -    ]}]}].

      Modify the default handler to only print errors and more severe log events to +standard_io:

      [{kernel,
      +  [{logger,
      +    [{handler, default, logger_std_h,  % {handler, HandlerId, Module,
      +      #{config => #{file => "log/erlang.log"}}}  % Config}
      +    ]}]}].

      Modify the default handler to print each log event as a single line:

      [{kernel,
      +  [{logger,
      +    [{handler, default, logger_std_h,
      +      #{formatter => {logger_formatter, #{single_line => true}}}}
      +    ]}]}].

      Modify the default handler to print the pid of the logging process for each log +event:

      [{kernel,
      +  [{logger,
      +    [{handler, default, logger_std_h,
      +      #{formatter => {logger_formatter,
      +                        #{template => [time," ",pid," ",msg,"\n"]}}}}
      +    ]}]}].

      Modify the default handler to only print errors and more severe log events to "log/erlang.log", and add another handler to print all log events to -"log/debug.log".

      [{kernel,
      -  [{logger,
      -    [{handler, default, logger_std_h,
      -      #{level => error,
      -        config => #{file => "log/erlang.log"}}},
      -     {handler, info, logger_std_h,
      -      #{level => debug,
      -        config => #{file => "log/debug.log"}}}
      -    ]}]}].

      Backwards Compatibility with error_logger

      Logger provides backwards compatibility with error_logger in the following +"log/debug.log".

      [{kernel,
      +  [{logger,
      +    [{handler, default, logger_std_h,
      +      #{level => error,
      +        config => #{file => "log/erlang.log"}}},
      +     {handler, info, logger_std_h,
      +      #{level => debug,
      +        config => #{file => "log/debug.log"}}}
      +    ]}]}].

      Backwards Compatibility with error_logger

      Logger provides backwards compatibility with error_logger in the following ways:

      • API for Logging - The error_logger API still exists, but should only be used by legacy code. It will be removed in a later release.

        Calls to error_logger:error_report/1,2, error_logger:error_msg/1,2, and corresponding @@ -315,9 +315,9 @@ information about the old SASL error logging functionality.

      • Legacy Event Handlers - To use event handlers written for error_logger, just add your event handler with

        error_logger:add_report_handler/1,2.

        This automatically starts the error logger event manager, and adds -error_logger as a handler to Logger, with the following configuration:

        #{level => info,
        +error_logger as a handler to Logger, with the following configuration:

        #{level => info,
           filter_default => log,
        -  filters => []}.

        Note

        This handler ignores events that do not originate from the error_logger + filters => []}.

        Note

        This handler ignores events that do not originate from the error_logger API, or from within OTP. This means that if your code uses the Logger API for logging, then your log events will be discarded by this handler.

        The handler is not overload protected.

      Error Handling

      Logger does, to a certain extent, check its input data before forwarding a log event to filters and handlers. It does, however, not evaluate report callbacks, @@ -330,20 +330,20 @@ about report callbacks and valid forms of log messages.

      Example: Add a handler to log info events to file

      When starting an Erlang node, the default behaviour is that all log events on level notice or more severe, are logged to the terminal via the default handler. To also log info events, you can either change the primary log level to -info:

      1> logger:set_primary_config(level, info).
      -ok

      or set the level for one or a few modules only:

      2> logger:set_module_level(mymodule, info).
      +info:

      1> logger:set_primary_config(level, info).
      +ok

      or set the level for one or a few modules only:

      2> logger:set_module_level(mymodule, info).
       ok

      This allows info events to pass through to the default handler, and be printed to the terminal as well. If there are many info events, it can be useful to print these to a file instead.

      First, set the log level of the default handler to notice, preventing it from -printing info events to the terminal:

      3> logger:set_handler_config(default, level, notice).
      +printing info events to the terminal:

      3> logger:set_handler_config(default, level, notice).
       ok

      Then, add a new handler which prints to file. You can use the handler module -logger_std_h, and configure it to log to file:

      4> Config = #{config => #{file => "./info.log"}, level => info}.
      -#{config => #{file => "./info.log"},level => info}
      -5> logger:add_handler(myhandler, logger_std_h, Config).
      +logger_std_h, and configure it to log to file:

      4> Config = #{config => #{file => "./info.log"}, level => info}.
      +#{config => #{file => "./info.log"},level => info}
      +5> logger:add_handler(myhandler, logger_std_h, Config).
       ok

      Since filter_default defaults to log, this handler now receives all log events. If you want info events only in the file, you must add a filter to stop -all non-info events. The built-in filter logger_filters:level/2 can do this:

      6> logger:add_handler_filter(myhandler, stop_non_info,
      -                             {fun logger_filters:level/2, {stop, neq, info}}).
      +all non-info events. The built-in filter logger_filters:level/2 can do this:

      6> logger:add_handler_filter(myhandler, stop_non_info,
      +                             {fun logger_filters:level/2, {stop, neq, info}}).
       ok

      See section Filters for more information about the filters and the filter_default configuration parameter.

      Example: Implement a handler

      logger_handler describes the callback functions that can be implemented for a Logger handler.

      A handler callback module must export:

      • log(Log, Config)

      It can optionally also export some, or all, of the following:

      • adding_handler(Config)
      • removing_handler(Config)
      • changing_config(SetOrUpdate, OldConfig, NewConfig)
      • filter_config(Config)

      When a handler is added, by for example a call to @@ -362,48 +362,48 @@ database.

      When logger:get_config/0 or logger:get_handler_config/0,1 is called, Logger calls HModule:filter_config(Config). This function must return the -handler configuration where internal data is removed.

      A simple handler that prints to the terminal can be implemented as follows:

      -module(myhandler1).
      --export([log/2]).
      +handler configuration where internal data is removed.

      A simple handler that prints to the terminal can be implemented as follows:

      -module(myhandler1).
      +-export([log/2]).
       
      -log(LogEvent, #{formatter := {FModule, FConfig}}) ->
      -    io:put_chars(FModule:format(LogEvent, FConfig)).

      Notice that the above handler does not have any overload protection, and all log +log(LogEvent, #{formatter := {FModule, FConfig}}) -> + io:put_chars(FModule:format(LogEvent, FConfig)).

      Notice that the above handler does not have any overload protection, and all log events are printed directly from the client process.

      For information and examples of overload protection, please refer to section Protecting the Handler from Overload, and the implementation of logger_std_h and logger_disk_log_h .

      The following is a simpler example of a handler which logs to a file through one -single process:

      -module(myhandler2).
      --export([adding_handler/1, removing_handler/1, log/2]).
      --export([init/1, handle_call/3, handle_cast/2, terminate/2]).
      +single process:

      -module(myhandler2).
      +-export([adding_handler/1, removing_handler/1, log/2]).
      +-export([init/1, handle_call/3, handle_cast/2, terminate/2]).
       
      -adding_handler(Config) ->
      -    MyConfig = maps:get(config,Config,#{file => "myhandler2.log"}),
      -    {ok, Pid} = gen_server:start(?MODULE, MyConfig, []),
      -    {ok, Config#{config => MyConfig#{pid => Pid}}}.
      +adding_handler(Config) ->
      +    MyConfig = maps:get(config,Config,#{file => "myhandler2.log"}),
      +    {ok, Pid} = gen_server:start(?MODULE, MyConfig, []),
      +    {ok, Config#{config => MyConfig#{pid => Pid}}}.
       
      -removing_handler(#{config := #{pid := Pid}}) ->
      -    gen_server:stop(Pid).
      +removing_handler(#{config := #{pid := Pid}}) ->
      +    gen_server:stop(Pid).
       
      -log(LogEvent,#{config := #{pid := Pid}} = Config) ->
      -    gen_server:cast(Pid, {log, LogEvent, Config}).
      +log(LogEvent,#{config := #{pid := Pid}} = Config) ->
      +    gen_server:cast(Pid, {log, LogEvent, Config}).
       
      -init(#{file := File}) ->
      /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_cookbook.xhtml differs (HTML document, ASCII text, with very long lines (1412))
      --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_cookbook.xhtml	2026-08-05 05:56:49.000000000 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_cookbook.xhtml	2026-08-05 05:56:49.000000000 +0000
      @@ -24,13 +24,13 @@
       post
       Erlang/OTP 21's new logger is
       a great starting point.

      Note

      If you find that some common Logger usage is missing from this guide, please -open a pull request on github with the suggested addition

      Get Logger information

      1> logger:i(primary).
      +open a pull request on github with the suggested addition

      Get Logger information

      1> logger:i(primary).
       Primary configuration:
           Level: notice
           Filter Default: log
           Filters:
      -        (none)

      It is also possible to fetch the configuration using -logger:get_primary_config().

      See also

      2> logger:i(handlers).
      +        (none)

      It is also possible to fetch the configuration using +logger:get_primary_config().

      See also

      2> logger:i(handlers).
       Handler configuration:
           Id: default
               Module: logger_std_h
      @@ -47,10 +47,10 @@
                       Arg: stop
                   Id: domain
                       Fun: fun logger_filters:domain/2
      -                Arg: {log,super,[otp,sasl]}
      +                Arg: {log,super,[otp,sasl]}
                   Id: no_domain
                       Fun: fun logger_filters:domain/2
      -                Arg: {log,undefined,[]}
      +                Arg: {log,undefined,[]}
               Handler Config:
                   burst_limit_enable: true
                   burst_limit_max_count: 500
      @@ -77,69 +77,69 @@
       =PROGRESS REPORT==== 4-Nov-2019::16:33:11.746546 ===
           application: stdlib
           started_at: nonode@nohost
      -Eshell V10.5.3  (abort with ^G)
      +Eshell V10.5.3  (abort with ^G)
       1>

      Configure Logger formatter

      In order to fit better into your existing logging infrastructure Logger can format its logging messages any way you want to. Either you can use the built-in formatter, or you can build your own.

      Single line configuration

      Since single line logging is the default of the built-in formatter you only have to provide the empty map as the configuration. The example below uses the sys.config to change the formatter configuration.

      $ cat sys.config
      -[{kernel,
      -  [{logger,
      -    [{handler, default, logger_std_h,
      -      #{ formatter => {logger_formatter, #{ }}}}]}]}].
      +[{kernel,
      +  [{logger,
      +    [{handler, default, logger_std_h,
      +      #{ formatter => {logger_formatter, #{ }}}}]}]}].
       $ erl -config sys
      -Eshell V10.5.1  (abort with ^G)
      -1> logger:error("Oh noes, an error").
      +Eshell V10.5.1  (abort with ^G)
      +1> logger:error("Oh noes, an error").
       1962-10-03T11:07:47.466763-04:00 error: Oh noes, an error

      However, if you just want to change it for the current session you can also do -that.

      1> logger:set_handler_config(default, formatter, {logger_formatter, #{}}).
      +that.

      1> logger:set_handler_config(default, formatter, {logger_formatter, #{}}).
       ok
      -2> logger:error("Oh noes, another error").
      +2> logger:error("Oh noes, another error").
       1962-10-04T15:34:02.648713-04:00 error: Oh noes, another error

      See also

      Add file and line number to log entries

      You can change what is printed to the log by using the formatter template:

      $ cat sys.config
      -[{kernel,
      -  [{logger,
      -    [{handler, default, logger_std_h,
      -      #{ formatter => {logger_formatter,
      -        #{ template => [time," ", file,":",line," ",level,": ",msg,"\n"] }}}}]}]}].
      +[{kernel,
      +  [{logger,
      +    [{handler, default, logger_std_h,
      +      #{ formatter => {logger_formatter,
      +        #{ template => [time," ", file,":",line," ",level,": ",msg,"\n"] }}}}]}]}].
       $ erl -config sys
      -Eshell V10.5.1  (abort with ^G)
      -1> logger:error("Oh noes, more errors",#{ file => "shell.erl", line => 1 }).
      +Eshell V10.5.1  (abort with ^G)
      +1> logger:error("Oh noes, more errors",#{ file => "shell.erl", line => 1 }).
       1962-10-05T07:37:44.104241+02:00 shell.erl:1 error: Oh noes, more errors

      Note that file and line have to be added in the metadata by the caller of logger:log/3 as otherwise Logger will not know from where it was called. The file and line number are automatically added if you use the ?LOG_ERROR macros in kernel/include/logger.hrl.

      See also

      Configuring handlers

      Instead of printing the logs to stdout we print them to a rotating file log.

      $ cat sys.config
      -[{kernel,
      -  [{logger,
      -    [{handler, default, logger_std_h,
      -      #{ config => #{ file => "log/erlang.log",
      +[{kernel,
      +  [{logger,
      +    [{handler, default, logger_std_h,
      +      #{ config => #{ file => "log/erlang.log",
                             max_no_bytes => 4096,
      -                      max_no_files => 5},
      -         formatter => {logger_formatter, #{}}}}]}]}].
      +                      max_no_files => 5},
      +         formatter => {logger_formatter, #{}}}}]}]}].
       $ erl -config sys
      -Eshell V10.5.1  (abort with ^G)
      -1> logger:error("Oh noes, even more errors").
      +Eshell V10.5.1  (abort with ^G)
      +1> logger:error("Oh noes, even more errors").
       ok
      -2> erlang:halt().
      +2> erlang:halt().
       $ cat log/erlang.log
       2019-10-07T11:47:16.837958+02:00 error: Oh noes, even more errors

      See also

      Debug only handler

      Add a handler that prints debug log events to a file, while the default handler prints only up to notice level events to standard out.

      $ cat sys.config
      -[{kernel,
      -  [{logger_level, all},
      -   {logger,
      -    [{handler, default, logger_std_h,
      -      #{ level => notice }},
      -     {handler, debug, logger_std_h,
      -      #{ filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],
      -         config => #{ file => "log/debug.log" } }}
      -    ]}]}].
      +[{kernel,
      +  [{logger_level, all},
      +   {logger,
      +    [{handler, default, logger_std_h,
      +      #{ level => notice }},
      +     {handler, debug, logger_std_h,
      +      #{ filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],
      +         config => #{ file => "log/debug.log" } }}
      +    ]}]}].
       $ erl -config sys
      -Eshell V10.5.1  (abort with ^G)
      -1> logger:error("Oh noes, even more errors").
      +Eshell V10.5.1  (abort with ^G)
      +1> logger:error("Oh noes, even more errors").
       =ERROR REPORT==== 9-Oct-2019::14:40:54.784162 ===
       Oh noes, even more errors
       ok
      -2> logger:debug("A debug event").
      +2> logger:debug("A debug event").
       ok
      -3> erlang:halt().
      +3> erlang:halt().
       $ cat log/debug.log
       2019-10-09T14:41:03.680541+02:00 debug: A debug event

      In the configuration above we first raise the primary log level to max in order for the debug log events to get to the handlers. Then we configure the default @@ -147,30 +147,30 @@ is all. Then the debug handler is configured with a filter to stop any log message that is not a debug level message.

      It is also possible to do the same changes in an already running system using the logger module. Then you do like this:

      $ erl
      -1> logger:set_handler_config(default, level, notice).
      +1> logger:set_handler_config(default, level, notice).
       ok
      -2> logger:add_handler(debug, logger_std_h, #{
      -  filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],
      -  config => #{ file => "log/debug.log" } }).
      +2> logger:add_handler(debug, logger_std_h, #{
      +  filters => [{debug,{fun logger_filters:level/2, {stop, neq, debug}}}],
      +  config => #{ file => "log/debug.log" } }).
       ok
      -3> logger:set_primary_config(level, all).
      +3> logger:set_primary_config(level, all).
       ok

      It is important that you do not raise the primary log level before adjusting the default handler's level as otherwise your standard out may be flooded by debug log messages.

      See also

      Logging

      What to log and how

      The simplest way to log something is by using the Logger macros and give a -report to the macro. For example if you want to log an error:

      ?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP }).

      This will print the following in the default log:

      =ERROR REPORT==== 10-Oct-2019::12:13:10.089073 ===
      +report to the macro. For example if you want to log an error:

      ?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP }).

      This will print the following in the default log:

      =ERROR REPORT==== 10-Oct-2019::12:13:10.089073 ===
           dst: {8,8,4,4}
           src: {8,8,8,8}
           status: 418
           what: http_error

      or the below if you use a single line formatter:

      2019-10-10T12:14:11.921843+02:00 error: dst: {8,8,4,4}, src: {8,8,8,8}, status: 418, what: http_error

      See also

      Report call-backs and printing of events

      If you want to do structured logging, but still want to have some control of how the final log message is formatted you can give a report_cb as part of the -metadata with your log event.

      ReportCB = fun(#{ what := What, status := Status, src := Src, dst := Dst }) ->
      -                   {ok, #hostent{ h_name = SrcName }} = inet:gethostbyaddr(Src),
      -                   {ok, #hostent{ h_name = DstName }} = inet:gethostbyaddr(Dst),
      -                   {"What: ~p~nStatus: ~p~nSrc: ~s (~s)~nDst: ~s (~s)~n",
      -                    [What, Status, inet:ntoa(Src), SrcName, inet:ntoa(Dst), DstName]}
      +metadata with your log event.

      ReportCB = fun(#{ what := What, status := Status, src := Src, dst := Dst }) ->
      +                   {ok, #hostent{ h_name = SrcName }} = inet:gethostbyaddr(Src),
      +                   {ok, #hostent{ h_name = DstName }} = inet:gethostbyaddr(Dst),
      +                   {"What: ~p~nStatus: ~p~nSrc: ~s (~s)~nDst: ~s (~s)~n",
      +                    [What, Status, inet:ntoa(Src), SrcName, inet:ntoa(Dst), DstName]}
                  end,
      -?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP },
      -           #{ report_cb => ReportCB }).

      This will print the following:

      =ERROR REPORT==== 10-Oct-2019::13:29:02.230863 ===
      +?LOG_ERROR(#{ what => http_error, status => 418, src => ClientIP, dst => ServerIP },
      +           #{ report_cb => ReportCB }).

      This will print the following:

      =ERROR REPORT==== 10-Oct-2019::13:29:02.230863 ===
       What: http_error
       Status: 418
       Src: 8.8.8.8 (dns.google)
      @@ -179,22 +179,22 @@
       single line formatter, however you can also use a report_cb fun with 2 arguments
       where the second argument is the formatting options.

      See also

      Filters

      Filters are used to remove or change log events before they reach the handlers.

      Process filters

      If we only want debug messages from a specific process it is possible to do this with a filter like this:

      %% Initial setup to use a filter for the level filter instead of the primary level
      -PrimaryLevel = maps:get(level, logger:get_primary_config()),
      -ok = logger:add_primary_filter(primary_level,
      -    {fun logger_filters:level/2, {log, gteq, PrimaryLevel}}),
      -logger:set_primary_config(filter_default, stop),
      -logger:set_primary_config(level, all),
      +PrimaryLevel = maps:get(level, logger:get_primary_config()),
      +ok = logger:add_primary_filter(primary_level,
      +    {fun logger_filters:level/2, {log, gteq, PrimaryLevel}}),
      +logger:set_primary_config(filter_default, stop),
      +logger:set_primary_config(level, all),
       
       %% Test that things work as they should
      /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_disk_log_h.xhtml differs (HTML document, ASCII text, with very long lines (463))
      --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_disk_log_h.xhtml	2026-08-05 05:56:49.000000000 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_disk_log_h.xhtml	2026-08-05 05:56:49.000000000 +0000
      @@ -58,12 +58,12 @@
       and the disk_log handler, and are documented in the
       User's Guide.

      Notice that when changing the configuration of the handler in runtime, the disk_log options (file, type, max_no_files, max_no_bytes) must not be -modified.

      Example of adding a disk_log handler:

      logger:add_handler(my_disk_log_h, logger_disk_log_h,
      -                   #{config => #{file => "./my_disk_log",
      +modified.

      Example of adding a disk_log handler:

      logger:add_handler(my_disk_log_h, logger_disk_log_h,
      +                   #{config => #{file => "./my_disk_log",
                                        type => wrap,
                                        max_no_files => 4,
                                        max_no_bytes => 10000,
      -                                 filesync_repeat_interval => 1000}}).

      To use the disk_log handler instead of the default standard handler when + filesync_repeat_interval => 1000}}).

      To use the disk_log handler instead of the default standard handler when starting an Erlang node, change the Kernel default logger to use logger_disk_log_h. Example:

      erl -kernel logger '[{handler,default,logger_disk_log_h,
                             #{config => #{file => "./system_disk_log"}}}]'

      See Also

      logger, logger_std_h, disk_log

      /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_filters.xhtml differs (HTML document, ASCII text, with very long lines (1103)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_filters.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_filters.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -128,8 +128,8 @@ events from, for example, a specific functional area. This allows filtering or other specialized treatment in a Logger handler.

      A domain field must be a list of atoms, creating smaller and more specialized domains as the list grows longer. The greatest domain is [], which comprises -all possible domains.

      For example, consider the following domains:

      D1 = [otp]
      -D2 = [otp, sasl]

      D1 is the greatest of the two, and is said to be a super-domain of D2. D2 +all possible domains.

      For example, consider the following domains:

      D1 = [otp]
      +D2 = [otp, sasl]

      D1 is the greatest of the two, and is said to be a super-domain of D2. D2 is a sub-domain D1. Both D1 and D2 are sub-domains of [].

      The above domains are used for logs originating from Erlang/OTP. D1 specifies that the log event comes from Erlang/OTP in general, and D2 indicates that the log event is a so called SASL report.

      The Extra parameter to the domain/2 function is specified when @@ -144,11 +144,11 @@ filter matches and Action is stop, the log event is stopped.

      If the filter does not match, it returns ignore, meaning that other filters, or the value of the configuration parameter filter_default, decide if the event is allowed or not.

      Log events that do not contain any domain field, match only when Compare is -equal to undefined or not_equal.

      Example: stop all events with domain [otp, sasl | _]

      1> logger:set_handler_config(h1, filter_default, log). % this is the default
      +equal to undefined or not_equal.

      Example: stop all events with domain [otp, sasl | _]

      1> logger:set_handler_config(h1, filter_default, log). % this is the default
       ok
      -2> Filter = {fun logger_filters:domain/2, {stop, sub, [otp, sasl]}}.
      +2> Filter = {fun logger_filters:domain/2, {stop, sub, [otp, sasl]}}.
       ...
      -3> logger:add_handler_filter(h1, no_sasl, Filter).
      +3> logger:add_handler_filter(h1, no_sasl, Filter).
       ok
      @@ -193,9 +193,9 @@ filter matches if the value of Operator is:

      • neq - and the compare function returns lt or gt.

      • eq - and the compare function returns eq.

      • lt - and the compare function returns lt.

      • gt - and the compare function returns gt.

      • lteq - and the compare function returns lt or eq.

      • gteq - and the compare function returns gt or eq.

      If the filter matches and Action is log, the log event is allowed. If the filter matches and Action is stop, the log event is stopped.

      If the filter does not match, it returns ignore, meaning that other filters, or the value of the configuration parameter filter_default, will decide if the -event is allowed or not.

      Example: only allow debug level log events

      logger:set_handler_config(h1, filter_default, stop).
      -Filter = {fun logger_filters:level/2, {log, eq, debug}}.
      -logger:add_handler_filter(h1, debug_only, Filter).
      +event is allowed or not.

      Example: only allow debug level log events

      logger:set_handler_config(h1, filter_default, stop).
      +Filter = {fun logger_filters:level/2, {log, eq, debug}}.
      +logger:add_handler_filter(h1, debug_only, Filter).
       ok
      /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_std_h.xhtml differs (HTML document, ASCII text, with very long lines (610)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_std_h.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger_std_h.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -79,9 +79,9 @@ protection behaviour. The same parameters are used both in the standard handler and the disk_log handler, and are documented in the User's Guide.

      Notice that if changing the configuration of the handler in runtime, the type, -file, or modes parameters must not be modified.

      Example of adding a standard handler:

      logger:add_handler(my_standard_h, logger_std_h,
      -                   #{config => #{file => "./system_info.log",
      -                                 filesync_repeat_interval => 1000}}).

      To set the default handler, that starts initially with the Kernel application, +file, or modes parameters must not be modified.

      Example of adding a standard handler:

      logger:add_handler(my_standard_h, logger_std_h,
      +                   #{config => #{file => "./system_info.log",
      +                                 filesync_repeat_interval => 1000}}).

      To set the default handler, that starts initially with the Kernel application, to log to file instead of standard_io, change the Kernel default logger configuration. Example:

      erl -kernel logger '[{handler,default,logger_std_h,
                             #{config => #{file => "./log.log"}}}]'

      An example of how to replace the standard handler with a disk_log handler at /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger.xhtml differs (HTML document, ASCII text, with very long lines (1841)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/logger.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -24,20 +24,20 @@

      API module for Logger, the standard logging facility in Erlang/OTP.

      This module implements the main API for logging in Erlang/OTP. To create a log event, use the API functions or the log -macros, for example:

      ?LOG_ERROR("error happened because: ~p", [Reason]).   % With macro
      -logger:error("error happened because: ~p", [Reason]). % Without macro

      To configure the Logger backend, use +macros, for example:

      ?LOG_ERROR("error happened because: ~p", [Reason]).   % With macro
      +logger:error("error happened because: ~p", [Reason]). % Without macro

      To configure the Logger backend, use Kernel configuration parameters or configuration functions in the Logger API.

      By default, the Kernel application installs one log handler at system start. This handler is named default. It receives and processes standard log events produced by the Erlang runtime system, standard behaviours and different Erlang/OTP applications. The log events are by default printed to the terminal.

      If you want your systems logs to be printed to a file instead, you must configure the default handler to do so. The simplest way is to include the -following in your sys.config:

      [{kernel,
      -  [{logger,
      -    [{handler, default, logger_std_h,
      -      #{config => #{file => "path/to/file.log"}}}]}]}].

      For more information about:

      • the Logger facility in general, see the User's Guide.
      • how to configure Logger, see the +following in your sys.config:

        [{kernel,
        +  [{logger,
        +    [{handler, default, logger_std_h,
        +      #{config => #{file => "path/to/file.log"}}}]}]}].

        For more information about:

        Macros

        The following macros are defined in logger.hrl, which is included in a module -with the directive

            -include_lib("kernel/include/logger.hrl").
        • ?LOG_EMERGENCY(StringOrReport[,Metadata])
        • ?LOG_EMERGENCY(FunOrFormat,Args[,Metadata])
        • ?LOG_ALERT(StringOrReport[,Metadata])
        • ?LOG_ALERT(FunOrFormat,Args[,Metadata])
        • ?LOG_CRITICAL(StringOrReport[,Metadata])
        • ?LOG_CRITICAL(FunOrFormat,Args[,Metadata])
        • ?LOG_ERROR(StringOrReport[,Metadata])
        • ?LOG_ERROR(FunOrFormat,Args[,Metadata])
        • ?LOG_WARNING(StringOrReport[,Metadata])
        • ?LOG_WARNING(FunOrFormat,Args[,Metadata])
        • ?LOG_NOTICE(StringOrReport[,Metadata])
        • ?LOG_NOTICE(FunOrFormat,Args[,Metadata])
        • ?LOG_INFO(StringOrReport[,Metadata])
        • ?LOG_INFO(FunOrFormat,Args[,Metadata])
        • ?LOG_DEBUG(StringOrReport[,Metadata])
        • ?LOG_DEBUG(FunOrFormat,Args[,Metadata])
        • ?LOG(Level,StringOrReport[,Metadata])
        • ?LOG(Level,FunOrFormat,Args[,Metadata])

        All macros expand to a call to Logger, where Level is taken from the macro +with the directive

            -include_lib("kernel/include/logger.hrl").
        • ?LOG_EMERGENCY(StringOrReport[,Metadata])
        • ?LOG_EMERGENCY(FunOrFormat,Args[,Metadata])
        • ?LOG_ALERT(StringOrReport[,Metadata])
        • ?LOG_ALERT(FunOrFormat,Args[,Metadata])
        • ?LOG_CRITICAL(StringOrReport[,Metadata])
        • ?LOG_CRITICAL(FunOrFormat,Args[,Metadata])
        • ?LOG_ERROR(StringOrReport[,Metadata])
        • ?LOG_ERROR(FunOrFormat,Args[,Metadata])
        • ?LOG_WARNING(StringOrReport[,Metadata])
        • ?LOG_WARNING(FunOrFormat,Args[,Metadata])
        • ?LOG_NOTICE(StringOrReport[,Metadata])
        • ?LOG_NOTICE(FunOrFormat,Args[,Metadata])
        • ?LOG_INFO(StringOrReport[,Metadata])
        • ?LOG_INFO(FunOrFormat,Args[,Metadata])
        • ?LOG_DEBUG(StringOrReport[,Metadata])
        • ?LOG_DEBUG(FunOrFormat,Args[,Metadata])
        • ?LOG(Level,StringOrReport[,Metadata])
        • ?LOG(Level,FunOrFormat,Args[,Metadata])

        All macros expand to a call to Logger, where Level is taken from the macro name, or from the first argument in the case of the ?LOG macro. Location data is added to the metadata as described under the metadata/0 type definition.

        The call is wrapped in a case statement and will be evaluated only if Level is equal to or below the configured log level.

        See Also

        config, erlang, io, logger_disk_log_h, @@ -1718,26 +1718,26 @@ consistent no matter which handler the system uses. Normal usage is to add a call to logger:add_handlers/1 just after the processes that the handler needs are started, and pass the application's logger configuration as the argument. -For example:

        -behaviour(application).
        -start(_, []) ->
        -    case supervisor:start_link({local, my_sup}, my_sup, []) of
        -        {ok, Pid} ->
        -            ok = logger:add_handlers(my_app),
        -            {ok, Pid, []};
        +For example:

        -behaviour(application).
        +start(_, []) ->
        +    case supervisor:start_link({local, my_sup}, my_sup, []) of
        +        {ok, Pid} ->
        +            ok = logger:add_handlers(my_app),
        +            {ok, Pid, []};
                 Error -> Error
              end.

        This reads the logger configuration parameter from the my_app application and starts the configured handlers. The contents of the configuration use the same rules as the logger handler configuration.

        If the handler is meant to replace the default handler, the Kernel's default handler have to be disabled before the new handler is added. A sys.config file -that disables the Kernel handler and adds a custom handler could look like this:

        [{kernel,
        -  [{logger,
        +that disables the Kernel handler and adds a custom handler could look like this:

        [{kernel,
        +  [{logger,
             %% Disable the default Kernel handler
        -    [{handler, default, undefined}]}]},
        - {my_app,
        -  [{logger,
        +    [{handler, default, undefined}]}]},
        + {my_app,
        +  [{logger,
             %% Enable this handler as the default
        -    [{handler, default, my_handler, #{}}]}]}].
        +
        [{handler, default, my_handler, #{}}]}]}].
      @@ -2692,8 +2692,8 @@ -

      Update the formatter configuration for the specified handler.

      The new configuration is merged with the existing formatter configuration.

      To overwrite the existing configuration without any merge, use

      set_handler_config(HandlerId, formatter,
      -	      {FormatterModule, FormatterConfig}).
      +

      Update the formatter configuration for the specified handler.

      The new configuration is merged with the existing formatter configuration.

      To overwrite the existing configuration without any merge, use

      set_handler_config(HandlerId, formatter,
      +	      {FormatterModule, FormatterConfig}).
      @@ -2756,8 +2756,8 @@

      Update configuration data for the specified handler. This function behaves as if -it was implemented as follows:

      {ok, {_, Old}} = logger:get_handler_config(HandlerId),
      -logger:set_handler_config(HandlerId, maps:merge(Old, Config)).

      To overwrite the existing configuration without any merge, use +it was implemented as follows:

      {ok, {_, Old}} = logger:get_handler_config(HandlerId),
      +logger:set_handler_config(HandlerId, maps:merge(Old, Config)).

      To overwrite the existing configuration without any merge, use set_handler_config/2 .

      @@ -2850,8 +2850,8 @@

      Update primary configuration data for Logger. This function behaves as if it was -implemented as follows:

      Old = logger:get_primary_config(),
      -logger:set_primary_config(maps:merge(Old, Config)).

      To overwrite the existing configuration without any merge, use +implemented as follows:

      Old = logger:get_primary_config(),
      +logger:set_primary_config(maps:merge(Old, Config)).

      To overwrite the existing configuration without any merge, use set_primary_config/1 .

      @@ -2883,7 +2883,7 @@

      Set or update metadata to use when logging from current process

      If process metadata exists for the current process, this function behaves as if -it was implemented as follows:

      logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).

      If no process metadata exists, the function behaves as +it was implemented as follows:

      logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).

      If no process metadata exists, the function behaves as set_process_metadata/1 .

      @@ -2915,8 +2915,8 @@

      Update configuration data for the Logger proxy. This function behaves as if it -was implemented as follows:

      Old = logger:get_proxy_config(),
      -logger:set_proxy_config(maps:merge(Old, Config)).

      To overwrite the existing configuration without any merge, use +was implemented as follows:

      Old = logger:get_proxy_config(),
      +logger:set_proxy_config(maps:merge(Old, Config)).

      To overwrite the existing configuration without any merge, use set_proxy_config/1 .

      For more information about the proxy, see section Logger Proxy in the Kernel User's Guide.

      @@ -3574,13 +3574,13 @@

      Create a log event at the given log level, with the given message to be logged and metadata.

      Example:

      %% A plain string
      -1> logger:log(info, "Hello World").
      +1> logger:log(info, "Hello World").
       %% A plain string with metadata
      -2> logger:log(debug, "Hello World", #{ meta => data }).
      +2> logger:log(debug, "Hello World", #{ meta => data }).
       %% A format string with arguments
      -3> logger:log(warning, "The roof is on ~ts",[Cause]).
      +3> logger:log(warning, "The roof is on ~ts",[Cause]).
       %% A report
      -4> logger:log(warning, #{ what => roof, cause => Cause }).

      Equivalent to log(Level, FormatOrFun, Args, #{}) if called as +4> logger:log(warning, #{ what => roof, cause => Cause }).

      Equivalent to log(Level, FormatOrFun, Args, #{}) if called as log(Level, FormatOrFun, Args).

      @@ -3619,12 +3619,12 @@ useful in scenarios when the message/metadata is very expensive to compute. This is because the fun is only evaluated when the message/metadata is actually needed, which may be not at all if the log event is not to be logged. Examples:

      %% A plain string with expensive metadata
      -1> logger:info(fun([]) -> {"Hello World", #{ meta => expensive() }} end,[]).
      +1> logger:info(fun([]) -> {"Hello World", #{ meta => expensive() }} end,[]).
       %% An expensive report
      -2> logger:debug(fun(What) -> #{ what => What, cause => expensive() } end,roof).
      +2> logger:debug(fun(What) -> #{ what => What, cause => expensive() } end,roof).
       %% A plain string with expensive metadata and normal metadata
      -3> logger:debug(fun([]) -> {"Hello World", #{ meta => expensive() }} end,[],
      -               #{ meta => data }).

      When metadata is given both as an argument and returned from the fun they are +3> logger:debug(fun([]) -> {"Hello World", #{ meta => expensive() }} end,[], + #{ meta => data }).

      When metadata is given both as an argument and returned from the fun they are merged. If equal keys exists the values are taken from the metadata returned by the fun.

      /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/net_adm.xhtml differs (HTML document, ASCII text, with very long lines (671)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/net_adm.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/net_adm.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -363,8 +363,8 @@

      Returns the names and associated port numbers of the Erlang nodes that epmd -registered at the specified host.

      Similar to epmd -names, see erts:epmd.

      Returns {error, address} if epmd is not operational.

      Example:

      (arne@dunn)1> net_adm:names().
      -{ok,[{"arne",40262}]}
      +registered at the specified host.

      Similar to epmd -names, see erts:epmd.

      Returns {error, address} if epmd is not operational.

      Example:

      (arne@dunn)1> net_adm:names().
      +{ok,[{"arne",40262}]}
      /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/net_kernel.xhtml differs (HTML document, ASCII text, with very long lines (1008)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/net_kernel.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/net_kernel.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -26,9 +26,9 @@ operational for distributed Erlang to work. The purpose of this process is to implement parts of the BIFs spawn/4 and spawn_link/4, and to provide monitoring of the network.

      An Erlang node is started using command-line flag -name or -sname:

      $ erl -sname foobar

      It is also possible to call net_kernel:start(foobar, #{}) -directly from the normal Erlang shell prompt:

      1> net_kernel:start(foobar, #{name_domain => shortnames}).
      -{ok,<0.64.0>}
      -(foobar@gringotts)2>

      If the node is started with command-line flag -sname, the node name is +directly from the normal Erlang shell prompt:

      1> net_kernel:start(foobar, #{name_domain => shortnames}).
      +{ok,<0.64.0>}
      +(foobar@gringotts)2>

      If the node is started with command-line flag -sname, the node name is foobar@Host, where Host is the short name of the host (not the fully qualified domain name). If started with flag -name, the node name is foobar@Host, where Host is the fully qualified domain name. For more @@ -592,13 +592,13 @@ delivered before a nodeup message due to a new connection to the same node. Prior to OTP 23.0, this was not guaranteed to be the case.

    The format of the node status change messages depends on Options. If Options is the empty list or if net_kernel:monitor_nodes/1 is called, the format is as -follows:

    {nodeup, Node} | {nodedown, Node}
    -  Node = node()

    When Options is the empty map or empty list, the caller will only subscribe +follows:

    {nodeup, Node} | {nodedown, Node}
    +  Node = node()

    When Options is the empty map or empty list, the caller will only subscribe for status change messages for visible nodes. That is, only nodes that appear in the result of erlang:nodes/0.

    If Options equals anything other than the empty list, the format of the status -change messages is as follows:

    {nodeup, Node, Info} | {nodedown, Node, Info}
    -  Node = node()
    -  Info = #{Tag => Val} | [{Tag, Val}]

    Info is either a map or a list of 2-tuples. Its content depends on Options. +change messages is as follows:

    {nodeup, Node, Info} | {nodedown, Node, Info}
    +  Node = node()
    +  Info = #{Tag => Val} | [{Tag, Val}]

    Info is either a map or a list of 2-tuples. Its content depends on Options. If Options is a map, Info will also be a map. If Options is a list, Info will also be a list.

    When Options is a map, currently the following associations are allowed:

    • connection_id => boolean() - If the value of the association equals true, a connection_id => ConnectionId association will be included in the @@ -632,23 +632,23 @@ {node_type, visible} tuple will be included in the Info list.

    • nodedown_reason - The tuple {nodedown_reason, Reason} will be included in the Info list for nodedown messages.

      See the documentation of the nodedown_reason => boolean() association -above for information about possible Reason values.

    Example:

    (a@localhost)1> net_kernel:monitor_nodes(true, #{connection_id=>true, node_type=>all, nodedown_reason=>true}).
    +above for information about possible Reason values.

    Example:

    (a@localhost)1> net_kernel:monitor_nodes(true, #{connection_id=>true, node_type=>all, nodedown_reason=>true}).
     ok
    -(a@localhost)2> flush().
    -Shell got {nodeup,b@localhost,
    -                  #{connection_id => 3067552,node_type => visible}}
    -Shell got {nodeup,c@localhost,
    -                  #{connection_id => 13892107,node_type => hidden}}
    -Shell got {nodedown,b@localhost,
    -                    #{connection_id => 3067552,node_type => visible,
    -                      nodedown_reason => connection_closed}}
    -Shell got {nodedown,c@localhost,
    -                    #{connection_id => 13892107,node_type => hidden,
    -                      nodedown_reason => net_tick_timeout}}
    -Shell got {nodeup,b@localhost,
    -                  #{connection_id => 3067553,node_type => visible}}
    +(a@localhost)2> flush().
    +Shell got {nodeup,b@localhost,
    +                  #{connection_id => 3067552,node_type => visible}}
    +Shell got {nodeup,c@localhost,
    +                  #{connection_id => 13892107,node_type => hidden}}
    +Shell got {nodedown,b@localhost,
    +                    #{connection_id => 3067552,node_type => visible,
    +                      nodedown_reason => connection_closed}}
    +Shell got {nodedown,c@localhost,
    +                    #{connection_id => 13892107,node_type => hidden,
    +                      nodedown_reason => net_tick_timeout}}
    +Shell got {nodeup,b@localhost,
    +                  #{connection_id => 3067553,node_type => visible}}
     ok
    -(a@localhost)3>
    +
    (a@localhost)3>
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/net.xhtml differs (HTML document, Unicode text, UTF-8 text, with very long lines (573)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/net.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/net.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -448,13 +448,13 @@

    Interface address filtering selector function/0.

    For each ifaddrs entry, return either true to keep the entry or false to discard the entry.

    For example, to get an interface list which only contains -non-loopback inet interfaces:

    net:getifaddrs(
    -    fun (#{ addr  := #{family := inet},
    -            flags := Flags}) ->
    -          not lists:member(loopback, Flags);
    -        (_) ->
    +non-loopback inet interfaces:

    net:getifaddrs(
    +    fun (#{ addr  := #{family := inet},
    +            flags := Flags}) ->
    +          not lists:member(loopback, Flags);
    +        (_) ->
               false
    -    end).
    +
    end).
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/notes.xhtml differs (HTML document, ASCII text, with very long lines (18940)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/notes.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -20,9 +20,9 @@

    This document describes the changes made to the Kernel application.

    Kernel 10.6.3.3

    Fixed Bugs and Malfunctions

    • inet:info/1 could crash when calling for a closing (port) socket.

      Own Id: OTP-20173

    • Handling of the truncation bit in inet_res has been fixed so it properly falls back to querying over TCP after a truncated UDP reply.

      This fixes a bug introduced in OTP-28.4.2 - kernel-10.6.2 making a truncated UDP answer fail to parse and never execute the fallback, instead the name resolve operation fails.

      Own Id: OTP-20199 Aux Id: PR-11247

    Kernel 10.6.3.2

    Fixed Bugs and Malfunctions

    • gen_tcp_socket accept should explicitly inherit the same options as plain gen_tcp.

      Own Id: OTP-20057

    Kernel 10.6.3.1

    Fixed Bugs and Malfunctions

    • Incorrect TOS format when using gen_udp with socket backend

      Own Id: OTP-20131 Aux Id: OTP-20102, GH-10968

    • SCTP peeloff of an IPv6 socket, the peeled-off socket does not inherit the parent options as expected.

      Own Id: OTP-20134 Aux Id: PR-11007

    Kernel 10.6.3

    Fixed Bugs and Malfunctions

    • On Windows, sockets has to be bound when using 'socket'. Therefor when using gen_tcp with inet_backend = socket, gen_tcp_socket bind even if the caller has not provided an explicit bind address. In that case it attempts to locate a "proper" address on its own. But if the connect address is the loopback address, this could lead to an attempt to bind to an external interface. So, this has now been changed so that if the connect address is the loopback address, the loopback address will also be used when binding.

      Own Id: OTP-20104 Aux Id: #10968

    Kernel 10.6.2

    Fixed Bugs and Malfunctions

    • Before this patch, the Erlang/OTP built-in DNS resolver (inet_res) used a sequential, process-global 16-bit transaction ID for UDP queries and did not implement source port randomization. Response validation relied almost entirely on this ID. Together, this made DNS cache poisoning practical for an attacker who can observe one query or predict the next ID. The design conflicted with RFC 5452 recommendations for mitigating forged DNS answers.

      inet_res is intended for use in trusted network environments and with trusted recursive resolvers. Earlier documentation did not clearly state this deployment assumption, which could lead users to deploy the resolver in environments where faked DNS responses are possible.

      Therefore, the documentation is been updated to clarify that inet_res should only be used in trusted networks and with trusted recursive resolvers.

      The implementation is also improved to use strong random DNS transaction IDs and source ports for every DNS transaction. This should give ample protection against brute forcing fake DNS replies, known as DNS cache poisoning, but it still does not protect against, for example, an adversary in the path of the DNS transaction that can observe the random values before faking malicious replies, an attack known as DNS spoofing.

      For randomization to happen, the Crypto application has to be loaded, which most probably already should be the case for an Erlang node in an exposed network.

      If performance should become an issue, for applications within safe network environments, the previous light weight behaviour can be configured by setting the resolver option random to false.

      Own Id: OTP-20037 Aux Id: CVE-2026-28810, PR-10864

    Kernel 10.6.1

    Fixed Bugs and Malfunctions

    • A vulnerability has been resolved in the (undocumented, unsupported and unused in OTP) inet_dns_tsig module that leads to a validation bypass.

      If a request contained an error code (forbidden by spec), it was treated as a response and skipped the verification of the MAC. The user of the module would then receive an "all ok" response, depending on the use case, this could lead to such things as AXFR or UPDATE being allowed.

      The code has also been tightening up of the client side to make sure too large (bad) MAC sizes cannot be selected and the limit is the output size of the algorithm chosen.

      Own Id: OTP-20012 Aux Id: PR-10825

    Kernel 10.6

    Fixed Bugs and Malfunctions

    • The built in DNS resolver inet_res has been fixed to do a final request assuming that the request name is absolute, as customary for many DNS resolver client libraries.

      Own Id: OTP-19937 Aux Id: GH-10494, PR-10576

    Improvements and New Features

    • Added support for zstd compression in the file module.

      Own Id: OTP-19860 Aux Id: PR-10385

    • Release applications, tests, and documentation are now placed in their respective directories. Source SBOM with more packages.

      A make release application places only the necessary code in the release folder. The main change is that the documentation and examples are not part of the release folder anymore.

      make release_docs places the documentation in the released code under the doc folder.

      make release_tests places the tests in their own directory. It used to be the case that some source code was mixed with the tests, and this should not happen anymore.

      The Software Bill of Materials places the examples folders as if they are part of the SPDX-otp-<app>-doc packge, instead of placing examples as if they were running source code.

      Overall, this change cleans up many things that were not quite correct by definition, and everything should still continue to work as expected. To test a release, one can still run ./Install -minimal \pwd`and add the release to thePATH. After that, one can run tests as usual, going into the released tests directory, enteringtest_server` and running the emulator.

      Improves the source Software-Bill-of-Materials

      • The improvements adds new SPDX relations for asmjit and zlib to be optional_components_of the Erlang/OTP project.
      • The autoconf scripts in make and erts have now been categorised as build_tool_of the Erlang/OTP project.
      • All remaining configure, configure.ac, config.h.in, Makefile.in, Makefile.src, EMakefile, and GNUMakefile are now part of a specific SPDX package with relation build_tool_of the Erlang/OTP project.

      Own Id: OTP-19886 Aux Id: PR-10434

    Kernel 10.5

    Fixed Bugs and Malfunctions

    • Fixed a shell crash when calling io:getopts() when user_drv process is not responding/terminating

      Own Id: OTP-19812 Aux Id: PR-10283

    • logger:get_handler_config/0 will no longer crash if a logger handler is removed concurrently with that call.

      Own Id: OTP-19837 Aux Id: PR-10308, GH-9997

    • Fixed a bug in the shell that made it incorrectly output a newline after the output already containing a newline but followed by an asci escape sequence.

      Own Id: OTP-19847 Aux Id: GH-10299

    Improvements and New Features

    • Receive buffer allocation has been optimized for socket socket in that an underutilized buffers' content is copied to a freshly allocated binary of the right size instead of being reallocated.

      This optimization was already implemented for the socket:recv/1 functions, but now the same buffer stragegy is shared between all socket receive operations.

      Own Id: OTP-19794 Aux Id: PR-10231

    • Option(s) to create gen_tcp and socket sockets with protocol IPPROTO_MPTCP has been implemented.

      See functions gen_tcp:listen/2, gen_tcp:connect/4 and the type socket:protocol/0.

      Own Id: OTP-19814

    • Support for the socket options TCP_KEEPCNT, TCP_KEEPIDLE, and TCP_KEEPINTVL have been implemented for gen_tcp, as well as TCP_USER_TIMEOUT for both gen_tcp and socket.

      Own Id: OTP-19857 Aux Id: OTP-19814, PR-10390

    • Limit size of sctp_event_subscribe on Linux

      Own Id: OTP-19863 Aux Id: PR-10321

    Kernel 10.4.2

    Fixed Bugs and Malfunctions

    • Fixed a race condition when registering the standard error process.

      Own Id: OTP-19832 Aux Id: PR-10290

    Kernel 10.4.1

    Fixed Bugs and Malfunctions

    • With this change group.erl will not crash when receiving unknown message.

      Own Id: OTP-19796 Aux Id: ERIERL-1264, PR-10248

    Kernel 10.4

    Fixed Bugs and Malfunctions

    • A remote shell can now exit by closing the input stream, without terminating the remote node.

      Own Id: OTP-19667 Aux Id: PR-9912

    • The internal inet_dns_tsig and inet_res modules have been fixed to TSIG verify the correct timestamp.

      In the process two undocumented error code atoms have been corrected to notauth and notzone to adhere to the DNS RFCs. Code that relied on the previous incorrect values may have to be corrected.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-19756 Aux Id: PR-10146

    Improvements and New Features

    • The rudimentary DNS resolver inet_res has aqcuired 3 new functions inet_res:gethostbyname/4, inet_res;getbyname/4 and inet_res:gethostbyaddr/3, that all take an option list argument.

      This option list can be used to override the Kernel application's resolver options when calling the inet_res function directly.

      Own Id: OTP-19737 Aux Id: ERIERL-1209, PR-10112

    Kernel 10.3.2

    Fixed Bugs and Malfunctions

    • socket:sendv/3 with 'nowait' sometimes return 'completion' without 'CompletionInfo' (Windows only).

      Own Id: OTP-19661

    • prim_net nif used incorrect encoding for family resulting in non-functional address selection.

      Own Id: OTP-19674

    • socket:accept can return unexpected 'select_sent'.

      Own Id: OTP-19684 Aux Id: ERIERL-1242

    • net_kernel could be blocked for a very long time when selecting distribution module for a connection if the DNS service was slow. This prevented any new connections to be set up during that time.

      Own Id: OTP-19702 Aux Id: ERIERL-1241, PR-10029

    Improvements and New Features

    • Improved documentation of CompletionStatus for asynchronous (nowait) socket operations.

      Own Id: OTP-19670 Aux Id: PR-9930

    Kernel 10.3.1

    Fixed Bugs and Malfunctions

    • Fix bug where calling io:setopts/1 in a shell without the line_history option would always disable line_history. This bug was introduced in Erlang/OTP 28.0.

      Own Id: OTP-19645 Aux Id: GH-9863, PR-9870

    Kernel 10.3

    Fixed Bugs and Malfunctions

    • Fixed an issue where output to the shell would not print the prompt on a new line.

      Own Id: OTP-19228 Aux Id: PR-8820

    • When in shell is in -noshell mode, and in latin1 encoding mode, io requests in latin1 encoding will not be translated to unicode and back to latin1.

      Own Id: OTP-19296 Aux Id: PR-9013

    • Fixed a bug where a composing unicode character would bind to a character not available to the user and deleting that character would cause a crash.

      Own Id: OTP-19297 Aux Id: PR-9005

    • The -noshell mode has been updated to read data lazily from standard input. Before this fix any data would be read greedily which meant that Erlang could consume data not meant for it. It also meant that in order for shell:start_interactive/0 to work on Windows an API that did not support reading of Unicode characters had to be used.

      Own Id: OTP-19313 Aux Id: PR-8962, GH-8113

    • The Erlang shell no longer crashes when a shell prompt ends with an escape sequence.

      Own Id: OTP-19414 Aux Id: PR-9272

    • code:get_doc/1 now works for cover-compiled modules.

      Own Id: OTP-19513 Aux Id: PR-9433

    • An infinite loop in CNAME loop detection that can cause Out Of Memory has been fixed. This affected CNAME lookup with the internal DNS resolver.

      Own Id: OTP-19544 Aux Id: PR-9587, OTP-19545

    • The internal resolver framework has been fixed to wait with the first resolver lookup until the ERL_INETRC environment variable has been applied.

      Previously, on some platform(s) (Linux) a first lookup when figuring out the domain name was always placed on the native resolver even if ERL_INETRC was used to disable it.

      Own Id: OTP-19555 Aux Id: PR-9543

    • Fix logger:add_handler(default, ...) to correctly replay events generated during startup when the default logger is set to undefined in logger's configuration parameters.

      Own Id: OTP-19588 Aux Id: PR-9595, GH-9436

    • Enhance specs of timeout for improving documentation and dialyzer analysis.

      Own Id: OTP-19604 Aux Id: PR-9574

    • Removed the default values for SCTP send (sndbuf) and receive (recbuf) buffers.

      Own Id: OTP-19627 Aux Id: OTP-19576, GH-9722

    Improvements and New Features

    • application:load/1 slows down as the number of directories in the code path increases because the call to code:where_is_file/1 for the '.app' file must scan each directory for the app.

      code_server maintains a cache of the contents of directories in the path. Re-using that cache when searching for '.app' files in application:load/1 may improve its runtime, especially when loading multiple applications.

      Own Id: OTP-19194 Aux Id: PR-8078

    • The Erlang SSH daemon now uses the same backend to handle multiline functionality as the Erlang shell.

      Own Id: OTP-19226 Aux Id: PR-8805

    • Added support for SIGWINCH, SIGCONT, and SIGINFO signals to os:set_signal/2 where available.

      Own Id: OTP-19278 Aux Id: PR-8887, PR-8938

    • Add net_kernel:allowed/0, it returns a list of nodes that are explicitly allowed to connect to the node by calling -net_kernel:allow/1

      Own Id: OTP-19287 Aux Id: PR-8207

    • Documentation chunks (EEP-48) has been updated to include the following reserved metadata fields: behaviours, group, source_path, and source_annos. The compiler has also been updated to emit this metadata. See the EEP-48 documentation for more details.

      Own Id: OTP-19306 Aux Id: PR-8945, PR-8975

    • The erpc:call/3, erpc:call/5, erpc:multicall/3, and erpc:multicall/5 functions now also accept an option map as last argument containing the timeout and always_spawn options. The always_spawn option can be used in order to ensure that the call operation will use a newly spawned process when executing the remote call.

      Own Id: OTP-19343 Aux Id: PR-8642

    • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

      All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

      -type meter() :: integer().
      --type foot() :: integer().

      Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

      -nominal meter() :: integer().
      --nominal foot() :: integer().

      More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

      Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

      Own Id: OTP-19364 Aux Id: PR-9079

    • Improved open debug for gen_tcp_socket (connect and listen) and gen_udp_socket (open).

      Own Id: OTP-19386

    • io:standard_error/0 has been updated to write via a NIF API instead of a port. This allows it to access the dirty-scheduler pool and make sure that writes have been written to the OSs stderr when io:format/3 and equivalent return.

      Own Id: OTP-19401 Aux Id: PR-9116

    • Added the option exception_on_failure to os:cmd/2 to make os:cmd/2 raise an exception if the command fails to execute.

      Own Id: OTP-19404 Aux Id: PR-9082

    • A socket option {otp,select_read} has been added that enables keeping a socket in the VM select/poll set between calls to recv functions.

      This increases throughput by reducing the number of calls to said functions.

      Own Id: OTP-19451 Aux Id: PR-9344

    • Add a configure chapter to the socket usage guide

      Own Id: OTP-19522 Aux Id: PR-9508

    • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

      Own Id: OTP-19575 Aux Id: PR-9670

    • Increase the default inet-driver buffer size(s). Also introduce kernel parameters for UDP and SCTP to change the sizes when creating (those) sockets.

      Own Id: OTP-19576

    • An experimental API for a native debugger has been added. The main components are the following:

      • A new compiler option beam_debug_info for the Erlang compiler. When given, most optimizations are disabled and debug information suitable for the native debugger are added to generated BEAM files.

      • A new +D emulator flag. When given, the VM becomes "debuggable", which means that when modules that been compiled with the beam_debug_info option are loaded, the code is instrumented so that one can enable and disable breakpoints on executable lines.

      • An experimental erl_debugger module with a new debugging API. Essentially, it allows a single, local, process to be registered as the "debugger" process for the node. This process is the one that will receive messages notifying that a process hit a breakpoint. This way, the front-end implementation of a debugger (such as edb from WhatApp) can be decoupled from OTP.

      • The erl_debugger module also exposes new BIFs to inspect X and Y registers of a suspended process. Together with new code-information BIFs, this let's a debugger show the values of variables in scope for a suspended process.

      Own Id: OTP-19609 Aux Id: PR-8670, PR-9334, PR-9604

    Kernel 10.2.7.4

    Fixed Bugs and Malfunctions

    • Before this patch, the Erlang/OTP built-in DNS resolver (inet_res) used a sequential, process-global 16-bit transaction ID for UDP queries and did not implement source port randomization. Response validation relied almost entirely on this ID. Together, this made DNS cache poisoning practical for an attacker who can observe one query or predict the next ID. The design conflicted with RFC 5452 recommendations for mitigating forged DNS answers.

      inet_res is intended for use in trusted network environments and with trusted recursive resolvers. Earlier documentation did not clearly state this deployment assumption, which could lead users to deploy the resolver in environments where faked DNS responses are possible.

      Therefore, the documentation is been updated to clarify that inet_res should only be used in trusted networks and with trusted recursive resolvers.

      The implementation is also improved to use strong random DNS transaction IDs and source ports for every DNS transaction. This should give ample protection against brute forcing fake DNS replies, known as DNS cache poisoning, but it still does not protect against, for example, an adversary in the path of the DNS transaction that can observe the random values before faking malicious replies, an attack known as DNS spoofing.

      For randomization to happen, the Crypto application has to be loaded, which most probably already should be the case for an Erlang node in an exposed network.

      If performance should become an issue, for applications within safe network environments, the previous light weight behaviour can be configured by setting the resolver option random to false.

      Own Id: OTP-20037 Aux Id: CVE-2026-28810, PR-10864

    Kernel 10.2.7.3

    Improvements and New Features

    Kernel 10.2.7.2

    Fixed Bugs and Malfunctions

    • socket:sendv/3 with 'nowait' sometimes return 'completion' without 'CompletionInfo' (Windows only).

      Own Id: OTP-19661

    • socket:accept can return unexpected 'select_sent'.

      Own Id: OTP-19684 Aux Id: ERIERL-1242

    • net_kernel could be blocked for a very long time when selecting distribution module for a connection if the DNS service was slow. This prevented any new connections to be set up during that time.

      Own Id: OTP-19702 Aux Id: ERIERL-1241, PR-10029

    Improvements and New Features

    • Improved documentation of CompletionStatus for asynchronous (nowait) socket operations.

      Own Id: OTP-19670 Aux Id: PR-9930

    Kernel 10.2.7.1

    Fixed Bugs and Malfunctions

    • A remote shell can now exit by closing the input stream, without terminating the remote node.

      Own Id: OTP-19667 Aux Id: PR-9912

    Improvements and New Features

    • Document default buffer sizes

      Own Id: OTP-19640 Aux Id: GH-9722

    Kernel 10.2.7

    Fixed Bugs and Malfunctions

    • With this change, disk_log will not crash when using chunk_step/3 after log size was decreased.

      Own Id: OTP-19605 Aux Id: GH-9720, PR-9765

    • With this change, disk_log will not run into infinite loop when using chunk/2,3 after log size was decreased.

      Own Id: OTP-19608 Aux Id: GH-9707, PR-9767

    Kernel 10.2.6

    Fixed Bugs and Malfunctions

    • Fixed bug in call_memory tracing that could cause wildly incorrect reported memory values. Bug exists since OTP 27.1.

      Also fixed return type spec of trace:info/3.

      Own Id: OTP-19581 Aux Id: ERIERL-1219, PR-9706

    Kernel 10.2.5

    Fixed Bugs and Malfunctions

    • On Windows, using socket:sendv, a large IOV (size > MAX), the tail was not sent.

      Own Id: OTP-19482

    • gen_tcp connect with a sockaddr with loopback address failed.

      Own Id: OTP-19560 Aux Id: GH-9541

    • Remove debug printouts from gen_tcp_socket

      Own Id: OTP-19564

    Kernel 10.2.4

    Fixed Bugs and Malfunctions

    • Behavior for socket:recv/3 has been improved. The behavior has also been clarified in the documentation.

      Own Id: OTP-19469 Aux Id: #9172

    • An infinite loop in CNAME loop detection that can cause Out Of Memory has been fixed. This affected CNAME lookup with the internal DNS resolver.

      Own Id: OTP-19545 Aux Id: PR-9587, OTP-19544

    Kernel 10.2.3

    Fixed Bugs and Malfunctions

    • Clarify inet:setopts documentation

      Own Id: OTP-19416 Aux Id: PR-9248

    • Fix bug where log printouts would go missing when application_controller is stopping while log messages are being sent.

      This bug was introduced by OTP-19078 in Erlang/OTP 26.2.5.

      Own Id: OTP-19418 Aux Id: GH-9163, PR-9274

    • Fixes a bug in the socket type spec, which caused Dialyzer to reject some valid programs.

      Own Id: OTP-19429 Aux Id: PR-9295, PR-9379

    Kernel 10.2.2

    Fixed Bugs and Malfunctions

    • Fixed a couple of bugs that could make global's internal state inconsistent when a connection was reconnected.

      Own Id: OTP-19381 Aux Id: PR-9377, GH-9112, GH-9117

    Kernel 10.2.1

    Fixed Bugs and Malfunctions

    • Fix the default group_leader to reply {error,request} on invalid I/O requests instead of crashing.

      This bug was introduced in Erlang/OTP 27.2.

      Own Id: OTP-19444 Aux Id: GH-9237, PR-9318

    Kernel 10.2

    Fixed Bugs and Malfunctions

    • gen_sctp:peeloff/2 has been fixed to inherit socket options to the peeled off socket more like gen_tcp:accept/1, for example the options tos or tclass.

      When setting SCTP options that are unsupported on the platform, some should be silently ignored, but a bug caused the option parsing to derail so the options after could bail out and cause an error instead. This has been fixed.

      Own Id: OTP-19225 Aux Id: PR-8789

    • Made it possible to expand help text displayed by pressing ^[h by pressing ^[h again.

      Own Id: OTP-19260 Aux Id: PR-8884

    • inet:getifaddrs/0,1 is improved when using +net_kernel:allow/1

      Own Id: OTP-19287 Aux Id: PR-8207

    • Documentation chunks (EEP-48) has been updated to include the following reserved metadata fields: behaviours, group, source_path, and source_annos. The compiler has also been updated to emit this metadata. See the EEP-48 documentation for more details.

      Own Id: OTP-19306 Aux Id: PR-8945, PR-8975

    • The erpc:call/3, erpc:call/5, erpc:multicall/3, and erpc:multicall/5 functions now also accept an option map as last argument containing the timeout and always_spawn options. The always_spawn option can be used in order to ensure that the call operation will use a newly spawned process when executing the remote call.

      Own Id: OTP-19343 Aux Id: PR-8642

    • EEP-69: Nominal Types has been implemented. As a side effect, nominal types can encode opaque types. We changed all opaque-handling logic and improved opaque warnings in Dialyzer.

      All existing Erlang type systems are structural: two types are seen as equivalent if their structures are the same. Type comparisons are based on the structures of the types, not on how the user explicitly defines them. For example, in the following example, meter() and foot() are equivalent. The two types can be used interchangeably. Neither of them differ from the basic type integer().

      -type meter() :: integer().
      +-type foot() :: integer().

      Nominal typing is an alternative type system, where two types are equivalent if and only if they are declared with the same type name. The EEP proposes one new syntax -nominal for declaring nominal types. Under nominal typing, meter() and foot() are no longer compatible. Whenever a function expects type meter(), passing in type foot() would result in a Dialyzer error.

      -nominal meter() :: integer().
      +-nominal foot() :: integer().

      More nominal type-checking rules can be found in the EEP. It is worth noting that most work for adding nominal types and type-checking is in erl_types.erl. The rest are changes that removed the previous opaque type-checking, and added an improved version of it using nominal type-checking with reworked warnings.

      Backwards compatibility for opaque type-checking is not preserved by this PR. Previous opaque warnings can appear with slightly different wordings. A new kind of opaque warning opaque_union is added, together with a Dialyzer option no_opaque_union to turn this kind of warnings off.

      Own Id: OTP-19364 Aux Id: PR-9079

    • Improved open debug for gen_tcp_socket (connect and listen) and gen_udp_socket (open).

      Own Id: OTP-19386

    • io:standard_error/0 has been updated to write via a NIF API instead of a port. This allows it to access the dirty-scheduler pool and make sure that writes have been written to the OSs stderr when io:format/3 and equivalent return.

      Own Id: OTP-19401 Aux Id: PR-9116

    • Added the option exception_on_failure to os:cmd/2 to make os:cmd/2 raise an exception if the command fails to execute.

      Own Id: OTP-19404 Aux Id: PR-9082

    • A socket option {otp,select_read} has been added that enables keeping a socket in the VM select/poll set between calls to recv functions.

      This increases throughput by reducing the number of calls to said functions.

      Own Id: OTP-19451 Aux Id: PR-9344

    • Add a configure chapter to the socket usage guide

      Own Id: OTP-19522 Aux Id: PR-9508

    • The license and copyright header has changed format to include an SPDX-License-Identifier. At the same time, most files have been updated to follow a uniform standard for license headers.

      Own Id: OTP-19575 Aux Id: PR-9670

    • Increase the default inet-driver buffer size(s). Also introduce kernel parameters for UDP and SCTP to change the sizes when creating (those) sockets.

      Own Id: OTP-19576

    • An experimental API for a native debugger has been added. The main components are the following:

      • A new compiler option beam_debug_info for the Erlang compiler. When given, most optimizations are disabled and debug information suitable for the native debugger are added to generated BEAM files.

      • A new +D emulator flag. When given, the VM becomes "debuggable", which means that when modules that been compiled with the beam_debug_info option are loaded, the code is instrumented so that one can enable and disable breakpoints on executable lines.

      • An experimental erl_debugger module with a new debugging API. Essentially, it allows a single, local, process to be registered as the "debugger" process for the node. This process is the one that will receive messages notifying that a process hit a breakpoint. This way, the front-end implementation of a debugger (such as edb from WhatApp) can be decoupled from OTP.

      • The erl_debugger module also exposes new BIFs to inspect X and Y registers of a suspended process. Together with new code-information BIFs, this let's a debugger show the values of variables in scope for a suspended process.

      Own Id: OTP-19609 Aux Id: PR-8670, PR-9334, PR-9604

    Kernel 10.2.7.4

    Fixed Bugs and Malfunctions

    • Before this patch, the Erlang/OTP built-in DNS resolver (inet_res) used a sequential, process-global 16-bit transaction ID for UDP queries and did not implement source port randomization. Response validation relied almost entirely on this ID. Together, this made DNS cache poisoning practical for an attacker who can observe one query or predict the next ID. The design conflicted with RFC 5452 recommendations for mitigating forged DNS answers.

      inet_res is intended for use in trusted network environments and with trusted recursive resolvers. Earlier documentation did not clearly state this deployment assumption, which could lead users to deploy the resolver in environments where faked DNS responses are possible.

      Therefore, the documentation is been updated to clarify that inet_res should only be used in trusted networks and with trusted recursive resolvers.

      The implementation is also improved to use strong random DNS transaction IDs and source ports for every DNS transaction. This should give ample protection against brute forcing fake DNS replies, known as DNS cache poisoning, but it still does not protect against, for example, an adversary in the path of the DNS transaction that can observe the random values before faking malicious replies, an attack known as DNS spoofing.

      For randomization to happen, the Crypto application has to be loaded, which most probably already should be the case for an Erlang node in an exposed network.

      If performance should become an issue, for applications within safe network environments, the previous light weight behaviour can be configured by setting the resolver option random to false.

      Own Id: OTP-20037 Aux Id: CVE-2026-28810, PR-10864

    Kernel 10.2.7.3

    Improvements and New Features

    Kernel 10.2.7.2

    Fixed Bugs and Malfunctions

    • socket:sendv/3 with 'nowait' sometimes return 'completion' without 'CompletionInfo' (Windows only).

      Own Id: OTP-19661

    • socket:accept can return unexpected 'select_sent'.

      Own Id: OTP-19684 Aux Id: ERIERL-1242

    • net_kernel could be blocked for a very long time when selecting distribution module for a connection if the DNS service was slow. This prevented any new connections to be set up during that time.

      Own Id: OTP-19702 Aux Id: ERIERL-1241, PR-10029

    Improvements and New Features

    • Improved documentation of CompletionStatus for asynchronous (nowait) socket operations.

      Own Id: OTP-19670 Aux Id: PR-9930

    Kernel 10.2.7.1

    Fixed Bugs and Malfunctions

    • A remote shell can now exit by closing the input stream, without terminating the remote node.

      Own Id: OTP-19667 Aux Id: PR-9912

    Improvements and New Features

    • Document default buffer sizes

      Own Id: OTP-19640 Aux Id: GH-9722

    Kernel 10.2.7

    Fixed Bugs and Malfunctions

    • With this change, disk_log will not crash when using chunk_step/3 after log size was decreased.

      Own Id: OTP-19605 Aux Id: GH-9720, PR-9765

    • With this change, disk_log will not run into infinite loop when using chunk/2,3 after log size was decreased.

      Own Id: OTP-19608 Aux Id: GH-9707, PR-9767

    Kernel 10.2.6

    Fixed Bugs and Malfunctions

    • Fixed bug in call_memory tracing that could cause wildly incorrect reported memory values. Bug exists since OTP 27.1.

      Also fixed return type spec of trace:info/3.

      Own Id: OTP-19581 Aux Id: ERIERL-1219, PR-9706

    Kernel 10.2.5

    Fixed Bugs and Malfunctions

    • On Windows, using socket:sendv, a large IOV (size > MAX), the tail was not sent.

      Own Id: OTP-19482

    • gen_tcp connect with a sockaddr with loopback address failed.

      Own Id: OTP-19560 Aux Id: GH-9541

    • Remove debug printouts from gen_tcp_socket

      Own Id: OTP-19564

    Kernel 10.2.4

    Fixed Bugs and Malfunctions

    • Behavior for socket:recv/3 has been improved. The behavior has also been clarified in the documentation.

      Own Id: OTP-19469 Aux Id: #9172

    • An infinite loop in CNAME loop detection that can cause Out Of Memory has been fixed. This affected CNAME lookup with the internal DNS resolver.

      Own Id: OTP-19545 Aux Id: PR-9587, OTP-19544

    Kernel 10.2.3

    Fixed Bugs and Malfunctions

    • Clarify inet:setopts documentation

      Own Id: OTP-19416 Aux Id: PR-9248

    • Fix bug where log printouts would go missing when application_controller is stopping while log messages are being sent.

      This bug was introduced by OTP-19078 in Erlang/OTP 26.2.5.

      Own Id: OTP-19418 Aux Id: GH-9163, PR-9274

    • Fixes a bug in the socket type spec, which caused Dialyzer to reject some valid programs.

      Own Id: OTP-19429 Aux Id: PR-9295, PR-9379

    Kernel 10.2.2

    Fixed Bugs and Malfunctions

    • Fixed a couple of bugs that could make global's internal state inconsistent when a connection was reconnected.

      Own Id: OTP-19381 Aux Id: PR-9377, GH-9112, GH-9117

    Kernel 10.2.1

    Fixed Bugs and Malfunctions

    • Fix the default group_leader to reply {error,request} on invalid I/O requests instead of crashing.

      This bug was introduced in Erlang/OTP 27.2.

      Own Id: OTP-19444 Aux Id: GH-9237, PR-9318

    Kernel 10.2

    Fixed Bugs and Malfunctions

    • gen_sctp:peeloff/2 has been fixed to inherit socket options to the peeled off socket more like gen_tcp:accept/1, for example the options tos or tclass.

      When setting SCTP options that are unsupported on the platform, some should be silently ignored, but a bug caused the option parsing to derail so the options after could bail out and cause an error instead. This has been fixed.

      Own Id: OTP-19225 Aux Id: PR-8789

    • Made it possible to expand help text displayed by pressing ^[h by pressing ^[h again.

      Own Id: OTP-19260 Aux Id: PR-8884

    • inet:getifaddrs/0,1 is improved when using inet_backend = socket.

      Own Id: OTP-19264

    • Fixed logger:report/0 to mandate at least one element in the report. This fixes an issue with overlapping spec domains in all logger functions that use logger:report/0.

      Own Id: OTP-19302 Aux Id: PR-8959

    • Fixed deadlock on code_server. Multiple calls loading the same module with an on_load function loading call would create a deadlock.

      Own Id: OTP-19305 Aux Id: PR-8744, GH-7466, GH-8510

    Improvements and New Features

    • The Kernel application now recognizes the epmd_module and erl_epmd_listen_port parameters, similar to -kernel:connect_all.

      Own Id: OTP-19253 Aux Id: PR-8671

    • The inetrc kernel argument will now tolerate atoms again to improve compatibility with old configurations that relied on atoms working by accident.

      The expected type always was, and still remains, a string.

      Own Id: OTP-19280 Aux Id: GH-8899, PR-8902

    • The file:io_device/0 type has been updated to clearly show the difference between a raw and cooked IoDevice.

      Own Id: OTP-19301 Aux Id: PR-8956

    • Erlang/OTP type specifications has been updated to eliminate overlapping domains.

      Own Id: OTP-19310 Aux Id: GH-8810, GH-8821, PR-8986

    • Added the kernel parameter os_cmd_shell that controls which shell should be used by os:cmd/1.

      Own Id: OTP-19342 Aux Id: PR-8972

    • Added logging support to io:user/0, io:standard_io/0 and io:standard_error/0. See io:setopts/2 for more details.

      Own Id: OTP-19372 Aux Id: PR-8947

    Kernel 10.1.2

    Fixed Bugs and Malfunctions

    • On windows the socket:recv could return with success ({ok, Data}) even though not all data had been read.

      Own Id: OTP-19328

    • gen_udp:send on domain local can leak inet_reply messages.

      Own Id: OTP-19332 Aux Id: #8989

    • Failure to create an UDP IPv6 socket when inet_backend = socket with certain IPv6 socket options.

      Own Id: OTP-19357

    • net:getifaddrs does not properly report the running flag on windows.

      Own Id: OTP-19366 Aux Id: OTP-19061, ERIERL-1134

    Kernel 10.1.1

    Fixed Bugs and Malfunctions

    • A bug has been fixed where receiving an SCTP message with gen_sctp could waste the first fragments of a message and only deliver the last fragment.

      This happened with low probability when the OS signaled that the socket was ready for reading in combination with an internal time-out retry.

      A bug has been fixed with a lingering time-out from after an SCTP connect that could stop the flow of incoming messages on an active gen_tcp socket.

      Own Id: OTP-19235 Aux Id: ERIERL-1133, PR-8837

    • An boolean option non_block_send for SCTP, has ben added to be able to achieve the old behaviour to avoid blocking send operations by passing the OS network stack error message ({error,eagain} through.

      Own Id: OTP-19258 Aux Id: OTP-19061, ERIERL-1134

    Kernel 10.1

    Fixed Bugs and Malfunctions

    • A faulty assertion was corrected in the prim_tty module. This assertion could trigger when invalid UTF-8 was read from stdin just as the mode was changed from unicode to latin1.

      Own Id: OTP-19097 Aux Id: PR-8503

    • Opening a disk_log file and combining head_func with rotate options did not work.

      Own Id: OTP-19104 Aux Id: ERIERL-870

    • Fixed an error info printout for erlang:is_process_alive/1 on non-local pids.

      Own Id: OTP-19134 Aux Id: PR-8560

    • A race in the kTLS flavour of SSL distribution has been fixed so that inet_drv.c doesn't read ahead too much data, which could cause the kTLS encryption to be activated too late when some encrypted data had already been read into the inet_drv.c buffer as unencrypted.

      Own Id: OTP-19175 Aux Id: GH-8561, PR-8690

    • Fixed a deadlock when an application crashes during startup and log messages were sent to standard out. Logger would fail to print the messages to standard out and instead print them to standard error.

      Own Id: OTP-19205

    • The -proto_dist init parameter will no longer be ignored when specified multiple times. It will now log a warning and use the first specified value.

      Own Id: OTP-19208 Aux Id: PR-8672

    • Corrected socket:ioctl for genaddr (SIOCGENADDR).

      Own Id: OTP-19216

    Improvements and New Features

    • Added functions getservbyname and getservbyport to the net module.

      Own Id: OTP-19101 Aux Id: OTP-18835

    • Introduced enet | esock variants of inet functions, either when called with sockets, with explicit inet_backend config or with the e inet_backend kernel config option.

      Own Id: OTP-19132 Aux Id: OTP-19101

    • The function socket:i/0 now uses the net module (instead of the inet module) for service translation.

      Own Id: OTP-19138 Aux Id: OTP-19101

    • A boolean option read_ahead has been implemented for gen_tcp, default true, to facilitate not reading past (caching data) the end of a packet. In particular, for kTLS, caching data could read in data that was supposed to be decrypted by the platform's network stack, before crypto parameters could be activated.

      Own Id: OTP-19199 Aux Id: OTP-19175, GH-8561, GH-8690, GH-8785

    Kernel 10.0.1

    Improvements and New Features

    • Polish the logger documentation.

      Own Id: OTP-19118 Aux Id: PR-8534

    Kernel 10.0

    Fixed Bugs and Malfunctions

    • Fixed a crash when calling file:delete/2 with an empty option list.

      Own Id: OTP-18590 Aux Id: PR-7220

    • New functions have been added to the undocumented module m:inet_dns that take a flag to specify if encode/decode is for mDNS. This affects how CLASS values in the private range, with the top bit set, are handled.

      Own Id: OTP-18878 Aux Id: GH-7718, OTP-17734

    • The error information for erlang:phash/2 has been corrected.

      Own Id: OTP-18904 Aux Id: PR-7960

    • get_until requests using the I/O protocol now correctly return a binary or list when eof is the last item returned by the callback.

      Own Id: OTP-18930 Aux Id: PR-7993, GH-4992

    • Calling logger:add_handlers/1 with config option now works.

      Own Id: OTP-18954 Aux Id: GH-8061, PR-8076

    • The code:del_path/1 function now also works on paths added through -pa, -pz , -path and the boot script.

      Own Id: OTP-18959 Aux Id: GH-6692, PR-7697

    • A call to socket:[recv|recvfrom|recvmsg]/* with Timeout = 0 on Windows could cause a (case clause) crash if data is immediately available.

      Own Id: OTP-19063 Aux Id: OTP-18835

    • Improve heuristic for when a characters is wide in the shell for systems with old libc versions.

      Own Id: OTP-19087 Aux Id: PR-8382

    • Fix reading a line when reading from io:user/0 to not consider \r without \n to be a new line when erl is started with -noshell.

      Own Id: OTP-19088 Aux Id: PR-8396, GH-8360

    Improvements and New Features

    • Added file:read_file/2 with a raw option for reading files without going through the file server.

      Own Id: OTP-18589 Aux Id: PR-7220

    • The undocumented Erlang DNS resolver library (inet_dns and inet_res) has been augmented to handle IXFR, NOTIFY, UPDATE and TSIG records. With this some bug fixes and code cleanup has been done, and the resolver used in the test suite has been changed to Knot DNS. See the source code.

      Kudos to Alexander Clouter that did almost all the work!

      Own Id: OTP-18713 Aux Id: PR-6985, GH-6985

    • The ebin directories for escripts are now cached.

      Own Id: OTP-18778 Aux Id: PR-7556

    • -callback attributes haven been added to application, logger_handler, and logger_formatter.

      Own Id: OTP-18795 Aux Id: PR-7703

    • Progress reports from before logger is started are now logged when log level is set to debug.

      Own Id: OTP-18807 Aux Id: PR-7732 ERIERL-985

    • The code:where_is_file/2 and code:which/1 functions now check for existence of the file directly instead of listing the content of each directory in the code path.

      Own Id: OTP-18816 Aux Id: PR-7711

    • Type specs has been added to the logger:Level/1,2,3 functions.

      Own Id: OTP-18820 Aux Id: PR-7779

    • For inet_backend = socket, setting the active socket option alone, to once, true or N has been optimized, as well as the corresponding data delivery.

      Own Id: OTP-18835

    • New functions socket:sendv/* for sending I/O vectors have been added.

      Own Id: OTP-18845

    • The shell now pages long output from the documentation help command (h(Module)), auto completions and the search command.

      Own Id: OTP-18846 Aux Id: PR-7845

    • Native coverage support has been implemented in the JIT. It will automatically be used by the cover tool to reduce the execution overhead when running cover-compiled code.

      There are also new APIs to support native coverage without using the cover tool.

      To instrument code for native coverage it must be compiled with the line_coverage option.

      To enable native coverage in the runtime system, start it like so:

      $ erl +JPcover true

      There are also the following new functions for supporting native coverage:

      Own Id: OTP-18856 Aux Id: PR-7856

    • Optimized code loading by moving certain operations from the code server to the caller.

      Own Id: OTP-18941 Aux Id: PR-7981

    • The documentation has been migrated to use Markdown and ExDoc.

      Own Id: OTP-18955 Aux Id: PR-8026

    • Application startup has been optimized by removing an intermediary process.

      Own Id: OTP-18963 Aux Id: PR-8042

    • The existing experimental support for archive files will be changed in a future release. The support for having an archive in an escript will remain, but the support for using archives in a release will either become more limited or completely removed.

      As of Erlang/OTP 27, the function code:lib_dir/2, the -code_path_choice flag, and using erl_prim_loader for reading members of an archive are deprecated.

      To remain compatible with future version of Erlang/OTP escript scripts that need to retrieve data files from its archive should use escript:extract/2 instead of erl_prim_loader and code:lib_dir/2.

      POTENTIAL INCOMPATIBILITY

      Own Id: OTP-18966 Aux Id: PR-8091

    • The undocumented and deprecated file:pid2name function has been removed.

      Own Id: OTP-18967 Aux Id: PR-8092

    • There is a new module trace in Kernel providing the same trace functionality as erlang:trace/3 and erlang:trace_pattern/3, but with the addition of dynamic isolated trace sessions.

      Own Id: OTP-18980

    • Error logging has been improved when the io:standard_io/0 reader and/or writer terminates with an error.

      Own Id: OTP-18989 Aux Id: PR-8103

    • inet_backend = socket has been optimized and reworked to be more compatible with the original inet_backend = inet.

      Own Id: OTP-19004 Aux Id: OTP-18835

    • Add an simple example (echo server) )to the socket users guide.

      Own Id: OTP-19042

    • inet:i/0,1,2 has been improved to allow port numbers to be shown explicitly.

      Own Id: OTP-19053 Aux Id: #6724

    • The socket documentation has been reworked, and due to @@ -1682,12 +1682,12 @@ viewed as two operations performed atomically. Asynchronously send an unlink signal or a demonitor signal, and ignore any future results of the link or monitor.

      NOTE: This change can cause some obscure code to fail which previously did -not. For example, the following code might hang:

                  Mon = erlang:monitor(process, Pid),
      +not. For example, the following code might hang:

                  Mon = erlang:monitor(process, Pid),
                   %% ...
      -            exit(Pid, bang),
      -            erlang:demonitor(Mon),
      +            exit(Pid, bang),
      +            erlang:demonitor(Mon),
                   receive
      -                {'DOWN', Mon, process, Pid, _} -> ok
      +                {'DOWN', Mon, process, Pid, _} -> ok
                   %% We were previously guaranteed to get a down message
                   %% (since we exited the process ourself), so we could
                   %% in this case leave out:
      /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/os.xhtml differs (HTML document, ASCII text, with very long lines (1354))
      --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/os.xhtml	2026-08-05 05:56:49.000000000 +0000
      +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/os.xhtml	2026-08-05 05:56:49.000000000 +0000
      @@ -536,19 +536,19 @@
             
       
       

      Executes Command in a command shell of the target OS, captures the standard -output and standard error of the command, and returns this result as a string.

      Examples:

      LsOut = os:cmd("ls"), % on unix platform
      -DirOut = os:cmd("dir"), % on Win32 platform

      Notice that in some cases, standard output of a command when called from another +output and standard error of the command, and returns this result as a string.

      Examples:

      LsOut = os:cmd("ls"), % on unix platform
      +DirOut = os:cmd("dir"), % on Win32 platform

      Notice that in some cases, standard output of a command when called from another program can differ, compared with the standard output of the command when called directly from an OS command shell.

      The possible options are:

      • max_size - The maximum size of the data returned by the os:cmd/2 call. This option is a safety feature that should be used when the command executed -can return a very large, possibly infinite, result.

        Example:

        > os:cmd("cat /dev/zero", #{ max_size => 20 }).
        -[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
      • exception_on_failure - If set to true, os:cmd/2 will throw an error +can return a very large, possibly infinite, result.

        Example:

        > os:cmd("cat /dev/zero", #{ max_size => 20 }).
        +[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
      • exception_on_failure - If set to true, os:cmd/2 will throw an error exception if the command exits with a non-zero exit code. The exception reason looks like this: {command_failed, ResultBeforeFailure, ExitCode} where ResultBeforeFailure is the result written to stdout by the command before -the error happened and ExitCode is the exit code from the command.

        Example:

        > catch os:cmd("echo hello && exit 123", #{ exception_on_failure => true }).
        -{'EXIT',{{command_failed,"hello\n",123},
        -         [{os,cmd,2,[{file,"os.erl"},{line,579}]},
        +the error happened and ExitCode is the exit code from the command.

        Example:

        > catch os:cmd("echo hello && exit 123", #{ exception_on_failure => true }).
        +{'EXIT',{{command_failed,"hello\n",123},
        +         [{os,cmd,2,[{file,"os.erl"},{line,579}]},
         ...

      The command shell can be set using the kernel configuration parameter, by default the shell is detected upon system startup.

      @@ -841,7 +841,7 @@ resolution timestamp.

      This counter is read directly from the hardware or operating system with the same guarantees. This means that two consecutive calls to the function are not guaranteed to be monotonic, though it most likely will be. The performance -counter will be converted to the resolution passed as an argument.

      1> T1 = os:perf_counter(1000),receive after 10000 -> ok end,T2 = os:perf_counter(1000).
      +counter will be converted to the resolution passed as an argument.

      1> T1 = os:perf_counter(1000),receive after 10000 -> ok end,T2 = os:perf_counter(1000).
       176525861
       2> T2 - T1.
       10004
      @@ -1012,16 +1012,16 @@ allows you to log time stamps in high resolution and consistent with the time in the rest of the OS.

      Example of code formatting a string in format "DD Mon YYYY HH:MM:SS.mmmmmm", where DD is the day of month, Mon is the textual month name, YYYY is the year, -HH:MM:SS is the time, and mmmmmm is the microseconds in six positions:

      -module(print_time).
      --export([format_utc_timestamp/0]).
      -format_utc_timestamp() ->
      -    TS = {_,_,Micro} = os:timestamp(),
      -    {{Year,Month,Day},{Hour,Minute,Second}} =
      -calendar:now_to_universal_time(TS),
      -    Mstr = element(Month,{"Jan","Feb","Mar","Apr","May","Jun","Jul",
      -    "Aug","Sep","Oct","Nov","Dec"}),
      -    io_lib:format("~2w ~s ~4w ~2w:~2..0w:~2..0w.~6..0w",
      -    [Day,Mstr,Year,Hour,Minute,Second,Micro]).

      This module can be used as follows:

      1> io:format("~s~n",[print_time:format_utc_timestamp()]).
      +HH:MM:SS is the time, and mmmmmm is the microseconds in six positions:

      -module(print_time).
      +-export([format_utc_timestamp/0]).
      +format_utc_timestamp() ->
      +    TS = {_,_,Micro} = os:timestamp(),
      +    {{Year,Month,Day},{Hour,Minute,Second}} =
      +calendar:now_to_universal_time(TS),
      +    Mstr = element(Month,{"Jan","Feb","Mar","Apr","May","Jun","Jul",
      +    "Aug","Sep","Oct","Nov","Dec"}),
      +    io_lib:format("~2w ~s ~4w ~2w:~2..0w:~2..0w.~6..0w",
      +    [Day,Mstr,Year,Hour,Minute,Second,Micro]).

      This module can be used as follows:

      1> io:format("~s~n",[print_time:format_utc_timestamp()]).
       29 Apr 2009  9:55:30.051711

      OS system time can also be retrieved by system_time/0 and system_time/1.

    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/pg.xhtml differs (HTML document, ASCII text, with very long lines (1156)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/pg.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/pg.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -742,7 +742,7 @@

    Subscribes the caller to updates from the specified scope.

    Returns content of the entire scope and a reference to match the upcoming notifications.

    Whenever any group membership changes, an update message is sent to the -subscriber:

    {Ref, join, Group, [JoinPid1, JoinPid2]}
    {Ref, leave, Group, [LeavePid1]}
    +subscriber:

    {Ref, join, Group, [JoinPid1, JoinPid2]}
    {Ref, leave, Group, [LeavePid1]}
    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/rpc.xhtml differs (HTML document, ASCII text, with very long lines (954)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/rpc.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/rpc.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -956,10 +956,10 @@ return values, or {badrpc, Reason} for failing calls. Timeout is a time (integer) in milliseconds, or infinity.

    The following example is useful when new object code is to be loaded on all nodes in the network, and indicates some side effects that RPCs can produce:

    %% Find object code for module Mod
    -{Mod, Bin, File} = code:get_object_code(Mod),
    +{Mod, Bin, File} = code:get_object_code(Mod),
     
     %% and load it on all nodes including this one
    -{ResL, _} = rpc:multicall(code, load_binary, [Mod, File, Bin]),
    +{ResL, _} = rpc:multicall(code, load_binary, [Mod, File, Bin]),
     
     %% and then maybe check the ResL list.

    Note

    If you want the ability to distinguish between results, you may want to consider using the erpc:multicall() function from the /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/seq_trace.xhtml differs (HTML document, ASCII text, with very long lines (839)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/seq_trace.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/seq_trace.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -29,9 +29,9 @@ how it can be used, see section Sequential Tracing.

    seq_trace provides functions that control all aspects of sequential tracing. There are functions for activation, deactivation, inspection, and for collection of the trace output.

    Trace Messages Sent to the System Tracer

    The format of the messages is one of the following, depending on if flag -timestamp of the trace token is set to true or false:

    {seq_trace, Label, SeqTraceInfo, TimeStamp}

    or

    {seq_trace, Label, SeqTraceInfo}

    Where:

    Label = int()
    -TimeStamp = {Seconds, Milliseconds, Microseconds}
    -  Seconds = Milliseconds = Microseconds = int()

    SeqTraceInfo can have the following formats:

    • {send, Serial, From, To, Message} - Used when a process From with its +timestamp of the trace token is set to true or false:

      {seq_trace, Label, SeqTraceInfo, TimeStamp}

      or

      {seq_trace, Label, SeqTraceInfo}

      Where:

      Label = int()
      +TimeStamp = {Seconds, Milliseconds, Microseconds}
      +  Seconds = Milliseconds = Microseconds = int()

      SeqTraceInfo can have the following formats:

      • {send, Serial, From, To, Message} - Used when a process From with its trace token flag send set to true has sent information. To may be a process identifier, a registered name on a node represented as {NameAtom, NodeAtom}, or a node name represented as an atom. From may be a @@ -127,68 +127,68 @@ C-nodes built with Erl_Interface too. A C-node built with Erl_Interface only maintains one trace token, which means that the C-node appears as one process from the sequential tracing point of view.

        Example of Use

        This example gives a rough idea of how the new primitives can be used and what -kind of output it produces.

        Assume that you have an initiating process with Pid == <0.30.0> like this:

        -module(seqex).
        --compile(export_all).
        +kind of output it produces.

        Assume that you have an initiating process with Pid == <0.30.0> like this:

        -module(seqex).
        +-compile(export_all).
         
        -loop(Port) ->
        +loop(Port) ->
             receive
        -        {Port,Message} ->
        -            seq_trace:set_token(label,17),
        -            seq_trace:set_token('receive',true),
        -            seq_trace:set_token(print,true),
        -            seq_trace:print(17,"**** Trace Started ****"),
        -            call_server ! {self(),the_message};
        -        {ack,Ack} ->
        +        {Port,Message} ->
        +            seq_trace:set_token(label,17),
        +            seq_trace:set_token('receive',true),
        +            seq_trace:set_token(print,true),
        +            seq_trace:print(17,"**** Trace Started ****"),
        +            call_server ! {self(),the_message};
        +        {ack,Ack} ->
                     ok
             end,
        -    loop(Port).

        And a registered process call_server with Pid == <0.31.0> like this:

        loop() ->
        +    loop(Port).

        And a registered process call_server with Pid == <0.31.0> like this:

        loop() ->
             receive
        -        {PortController,Message} ->
        -            Ack = {received, Message},
        -            seq_trace:print(17,"We are here now"),
        -            PortController ! {ack,Ack}
        +        {PortController,Message} ->
        +            Ack = {received, Message},
        +            seq_trace:print(17,"We are here now"),
        +            PortController ! {ack,Ack}
             end,
        -    loop().

        A possible output from the system's sequential_tracer can be like this:

        17:<0.30.0> Info {0,1} WITH
        +    loop().

        A possible output from the system's sequential_tracer can be like this:

        17:<0.30.0> Info {0,1} WITH
         "**** Trace Started ****"
        -17:<0.31.0> Received {0,2} FROM <0.30.0> WITH
        -{<0.30.0>,the_message}
        -17:<0.31.0> Info {2,3} WITH
        +17:<0.31.0> Received {0,2} FROM <0.30.0> WITH
        +{<0.30.0>,the_message}
        +17:<0.31.0> Info {2,3} WITH
         "We are here now"
        -17:<0.30.0> Received {2,4} FROM <0.31.0> WITH
        -{ack,{received,the_message}}

        The implementation of a system tracer process that produces this printout can -look like this:

        tracer() ->
        +17:<0.30.0> Received {2,4} FROM <0.31.0> WITH
        +{ack,{received,the_message}}

        The implementation of a system tracer process that produces this printout can +look like this:

        tracer() ->
             receive
        -        {seq_trace,Label,TraceInfo} ->
        -           print_trace(Label,TraceInfo,false);
        -        {seq_trace,Label,TraceInfo,Ts} ->
        -           print_trace(Label,TraceInfo,Ts);
        +        {seq_trace,Label,TraceInfo} ->
        +           print_trace(Label,TraceInfo,false);
        +        {seq_trace,Label,TraceInfo,Ts} ->
        +           print_trace(Label,TraceInfo,Ts);
                 _Other -> ignore
             end,
        -    tracer().
        +    tracer().
         
        -print_trace(Label,TraceInfo,false) ->
        -    io:format("~p:",[Label]),
        -    print_trace(TraceInfo);
        -print_trace(Label,TraceInfo,Ts) ->
        -    io:format("~p ~p:",[Label,Ts]),
        -    print_trace(TraceInfo).
        -
        -print_trace({print,Serial,From,_,Info}) ->
        -    io:format("~p Info ~p WITH~n~p~n", [From,Serial,Info]);
        -print_trace({'receive',Serial,From,To,Message}) ->
        -    io:format("~p Received ~p FROM ~p WITH~n~p~n",
        -              [To,Serial,From,Message]);
        -print_trace({send,Serial,From,To,Message}) ->
        -    io:format("~p Sent ~p TO ~p WITH~n~p~n",
        -              [From,Serial,To,Message]).

        The code that creates a process that runs this tracer function and sets that -process as the system tracer can look like this:

        start() ->
        -    Pid = spawn(?MODULE,tracer,[]),
        -    seq_trace:set_system_tracer(Pid), % set Pid as the system tracer
        -    ok.

        With a function like test/0, the whole example can be started:

        test() ->
        -    P = spawn(?MODULE, loop, [port]),
        -    register(call_server, spawn(?MODULE, loop, [])),
        -    start(),
        -    P ! {port,message}.
        +
        print_trace(Label,TraceInfo,false) -> + io:format("~p:",[Label]), + print_trace(TraceInfo); +print_trace(Label,TraceInfo,Ts) -> + io:format("~p ~p:",[Label,Ts]), + print_trace(TraceInfo). + +print_trace({print,Serial,From,_,Info}) -> + io:format("~p Info ~p WITH~n~p~n", [From,Serial,Info]); +print_trace({'receive',Serial,From,To,Message}) -> + io:format("~p Received ~p FROM ~p WITH~n~p~n", + [To,Serial,From,Message]); +print_trace({send,Serial,From,To,Message}) -> + io:format("~p Sent ~p TO ~p WITH~n~p~n", + [From,Serial,To,Message]).

        The code that creates a process that runs this tracer function and sets that +process as the system tracer can look like this:

        start() ->
        +    Pid = spawn(?MODULE,tracer,[]),
        +    seq_trace:set_system_tracer(Pid), % set Pid as the system tracer
        +    ok.

        With a function like test/0, the whole example can be started:

        test() ->
        +    P = spawn(?MODULE, loop, [port]),
        +    register(call_server, spawn(?MODULE, loop, [])),
        +    start(),
        +    P ! {port,message}.
    @@ -761,11 +761,11 @@ tracing is disabled, otherwise Token should be an Erlang term returned from get_token/0 or set_token/1. set_token/1 can be used to temporarily exclude message passing from the trace by setting the -trace token to empty like this:

    OldToken = seq_trace:set_token([]), % set to empty and save
    +trace token to empty like this:

    OldToken = seq_trace:set_token([]), % set to empty and save
                                         % old value
     % do something that should not be part of the trace
    -io:format("Exclude the signalling caused by this~n"),
    -seq_trace:set_token(OldToken), % activate the trace token again
    +io:format("Exclude the signalling caused by this~n"),
    +seq_trace:set_token(OldToken), % activate the trace token again
     ...

    Returns the previous value of the trace token.

    /usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/socket_usage.xhtml differs (HTML document, ASCII text, with very long lines (986)) --- old//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/socket_usage.xhtml 2026-08-05 05:56:49.000000000 +0000 +++ new//usr/share/doc/packages/erlang-doc/lib/kernel-10.6.3.3/doc/html/kernel.epub/OEBPS/socket_usage.xhtml 2026-08-05 05:56:49.000000000 +0000 @@ -57,59 +57,59 @@ socket:sendv/3 with asynchronous (nowait) on completion systems (Windows).
    Observe that this is not an illustration how to write a asynchronous sendv function. Its just an example of what kind of messages and results that can be expected. The example below basically (re-) implements: -socket:sendv(Sock, IOV, infinity).